zoukankan      html  css  js  c++  java
  • scrapy学习笔记

    crapy是python最有名的爬虫框架之一,可以很方便的进行web抓取,并且提供了很强的定制型,这里记录简单学习的过程和在实际应用中会遇到的一些常见问题

    一、安装

    在安装scrapy之前有一些依赖需要安装,否则可能会安装失败,scrapy的选择器依赖于lxml,还有Twisted网络引擎,下面是ubuntu下安装的过程

    1. linux下安装

     

    http://lxml.de/installation.html

    2. Mac下安装

    mac下安装有时候会失败,建议使用virtualenv安装在独立的环境下,可以减少一些问题,因为mac系统自带python,例如一些依赖库依赖的一些新的版本,而升级新版本会把旧版本卸载掉,卸载可能会有权限的问题

    二、基本使用

    1. 初始化scrapy项目

    我们可以使用命令行初始化一个项目

    这里可以查看scrapy更多其他的命令

    初始化完成后,我们得到下面目录结构

    我们先看一下scrapy的处理流程

    scrapy由下面几个部分组成

    • spiders:爬虫模块,负责配置需要爬取的数据和爬取规则,以及解析结构化数据
    • items:定义我们需要的结构化数据,使用相当于dict
    • pipelines:管道模块,处理spider模块分析好的结构化数据,如保存入库等
    • middlewares:中间件,相当于钩子,可以对爬取前后做预处理,如修改请求header,url过滤等

    我们先来看一个例子,在spiders目录下新建一个模块DmozSpider.py

    打开终端进入根目录,执行下面命令

    爬虫开始爬取start_urls定义的url,并输出到文件中,最后输出爬去报告,会输出爬取得统计结果

    这里我们完成了简单的爬取和保存的操作,会在根目录生成两个文件ResourcesBooks

    2. 通过代码运行爬虫

    每次进入控制台运行爬虫还是比较麻烦的,而且不好调试,我们可以通过CrawlerProcess通过代码运行爬虫,新建一个模块run.py

    参考:http://doc.scrapy.org/en/latest/topics/practices.html#run-scrapy-from-a-script

    三、Scrapy类

    如上面的DmozSpider类,爬虫类继承自scrapy.Spider,用于构造Request对象给Scheduler

    1. 常用属性与方法

    属性

    • name:爬虫的名字,必须唯一(如果在控制台使用的话,必须配置)
    • start_urls:爬虫初始爬取的链接列表
    • parse:response结果处理函数
    • custom_settings:自定义配置,覆盖settings.py中的默认配置

    方法

    • start_requests:启动爬虫的时候调用,默认是调用make_requests_from_url方法爬取start_urls的链接,可以在这个方法里面定制,如果重写了该方法,start_urls默认将不会被使用,可以在这个方法里面定制一些自定义的url,如登录,从数据库读取url等,本方法返回Request对象
    • make_requests_from_url:默认由start_requests调用,可以配置Request对象,返回Request对象
    • parse:response到达spider的时候默认调用,如果在Request对象配置了callback函数,则不会调用,parse方法可以迭代返回ItemRequest对象,如果返回Request对象,则会进行增量爬取

    2. Request与Response对象

    每个请求都是一个Request对象,Request对象定义了请求的相关信息(urlmethodheadersbodycookiepriority)和回调的相关信息(metacallbackdont_filtererrback),通常由spider迭代返回

    其中meta相当于附加变量,可以在请求完成后通过response.meta访问

    请求完成后,会通过Response对象发送给spider处理,常用属性有(urlstatusheadersbodyrequestmeta, )

    详细介绍参考官网

    看下面这个例子

    四、Selector

    上面我们只是爬取了网页的html文本,对于爬虫,我们需要明确我们需要爬取的结构化数据,需要对原文本进行解析,解析的方法通常有下面这些

    • 普通文本操作
    • 正则表达式:re
    • Dom树操作:BeautifulSoup
    • XPath选择器:lxml

    scrapy默认支持选择器的功能,自带的选择器构建与lxml之上,并对其进行了改进,使用起来更为简洁明了

    1. XPath选择器

    XPpath是标准的XML文档查询语言,可以用于查询XML文档中的节点和内容,关于XPath语法,可以参见这里

    先看一个例子,通过html或xml构造Selector对象,然后通过xpath查询节点,并解析出节点的内容

    Selector相当于节点,通过xpath去到子节点集合(SelectorList),可以继续搜索,通过extract方法可以取出节点的值,extract方法也可以作用于SelectorList,对于SelectorList可以通过extract_first取出第一个节点的值

    • 通过text()取出节点的内容
    • 通过@href去除节点属性值(这里是取出href属性的值)
    • 直接对节点取值,则是输出节点的字符串

    2. CSS选择器

    除了XPath选择器,scrapy还支持css选择器

    关于css选择器更多的规则,可以见w3c官网

    五、Item类

    上面我们只是爬取了网页的html文本,对于爬虫,我们需要明确我们需要爬取的结构化数据,我们定义一个item存储分类信息,scrapy的item继承自scrapy.Item

    scrapy.Item的用法与python中的字典用法基本一样,只是做了一些安全限制,属性定义使用Field,这里只是进行了声明,而不是真正的属性,使用的时候通过键值对操作,不支持属性访问

    what, 好坑爹,这意味着所有的属性赋值都得用字符串了,这里有解释(还是没太明白)

    修改DmozSpider的parse方法

    六、Pipeline

    spider负责爬虫的配置,item负责声明结构化数据,而对于数据的处理,在scrapy中使用管道的方式进行处理,只要注册过的管道都可以处理item数据(处理,过滤,保存)

    下面看看管道的声明方式,这里定义一个预处理管道PretreatmentPipeline.py,如果item的title为None,则设置为空字符串

    再定义一个过滤重复数据的管道DuplicatesPipeline.py,当link重复,则丢弃

    最后可以定义一个保存数据的管道,可以把数据保存到数据库中

    定义好管道之后我们需要配置到爬虫上,我们在settings.py模块中配置,后面的数字表示管道的顺序

    我们也可以为spider配置单独的pipeline

    除了process_item方法外,pipeline还有open_spiderspider_closed两个方法,在爬虫启动和关闭的时候调用

    七、Rule

    爬虫的通常需要在一个网页里面爬去其他的链接,然后一层一层往下爬,scrapy提供了LinkExtractor类用于对网页链接的提取,使用LinkExtractor需要使用CrawlSpider爬虫类中,CrawlSpiderSpider相比主要是多了rules,可以添加一些规则,先看下面这个例子,爬取链家网的链接

     

    1. Rule对象

    Role对象有下面参数

    • link_extractor:链接提取规则
    • callback:link_extractor提取的链接的请求结果的回调
    • cb_kwargs:附加参数,可以在回调函数中获取到
    • follow:表示提取的链接请求完成后是否还要应用当前规则(boolean),如果为False则不会对提取出来的网页进行进一步提取,默认为False
    • process_links:处理所有的链接的回调,用于处理从response提取的links,通常用于过滤(参数为link列表)
    • process_request:链接请求预处理(添加header或cookie等)

    2. LinkExtractor

    LinkExtractor常用的参数有:

    • allow:提取满足正则表达式的链接
    • deny:排除正则表达式匹配的链接(优先级高于allow
    • allow_domains:允许的域名(可以是strlist
    • deny_domains:排除的域名(可以是strlist
    • restrict_xpaths:提取满足XPath选择条件的链接(可以是strlist
    • restrict_css:提取满足css选择条件的链接(可以是strlist
    • tags:提取指定标签下的链接,默认从aarea中提取(可以是strlist
    • attrs:提取满足拥有属性的链接,默认为href(类型为list
    • unique:链接是否去重(类型为boolean
    • process_value:值处理函数(优先级大于allow

    关于LinkExtractor的详细参数介绍见官网

    注意:如果使用rules规则,请不要覆盖或重写CrawlSpiderparse方法,否则规则会失效,可以使用parse_start_urls方法

    八、Middleware

    从最开始的流程图可以看到,爬去一个资源链接的流程,首先我们配置spider相关的爬取信息,在启动爬取实例后,scrapy_engine从Spider取出Request(经过SpiderMiddleware),然后丢给Scheduler(经过SchedulerMiddleware),Scheduler接着把请求丢给Downloader(经过DownloadMiddlware),Downloader把请求结果丢还给Spider,然后Spider把分析好的结构化数据丢给Pipeline,Pipeline进行分析保存或丢弃,这里面有4个角色

    scrapy有下面三种middlewares

    • SpiderMiddleware:通常用于配置爬虫相关的属性,引用链接设置,Url长度限制,成功状态码设置,爬取深度设置,爬去优先级设置等
    • DownloadMiddlware:通常用于处理下载之前的预处理,如请求Header(Cookie,User-Agent),登录验证处理,重定向处理,代理服务器处理,超时处理,重试处理等
    • SchedulerMiddleware(已经废弃):为了简化框架,调度器中间件已经被废弃,使用另外两个中间件已经够用了

    1. SpiderMiddleware

    爬虫中间件有下面几个方法

    • process_spider_input:当response通过spider的时候被调用,返回None(继续给其他中间件处理)或抛出异常(不会给其他中间件处理,当成异常处理)
    • process_spider_output:当spider有item或Request输出的时候调动
    • process_spider_exception:处理出现异常时调用
    • process_start_requests:spider当开始请求Request的时候调用

    下面是scrapy自带的一些中间件(在scrapy.spidermiddlewares命名空间下)

    • UrlLengthMiddleware
    • RefererMiddleware
    • OffsiteMiddleware
    • HttpErrorMiddleware
    • DepthMiddleware

    我们自己实现一个SpiderMiddleware

    参考链接:http://doc.scrapy.org/en/latest/topics/spider-middleware.html

    2. DownloaderMiddleware

    下载中间件有下面几个方法

    • process_request:请求通过下载器的时候调用
    • process_response:请求完成后调用
    • process_exception:请求发生异常时调用
    • from_crawler:从crawler构造的时候调用
    • from_settings:从settings构造的时候调用

    更多详细的参数解释见这里

    在爬取网页的时候,使用不同的User-Agent可以提高请求的随机性,定义一个随机设置User-Agent的中间件RandomUserAgentMiddleware

    settings.py设置USER_AGENTS参数

    配置爬虫中间件的方式与pipeline类似,第二个参数表示优先级

    九、缓存

    scrapy默认已经自带了缓存的功能,通常我们只需要配置即可,打开settings.py

    更多参数参见这里

    十、多线程

    scrapy网络请求是基于Twisted,而Twisted默认支持多线程,而且scrapy默认也是通过多线程请求的,并且支持多核CPU的并发,通常只需要配置一些参数即可

    更多参数参见这里

    十一、常见问题

    1. 项目名称问题

    在使用的时候遇到过一个问题,在初始化scrapy startproject tutorial的时候,如果使用了一些特殊的名字,如:testfang等单词的话,通过get_project_settings方法获取配置的时候会出错,改成tutorial或一些复杂的名字的时候不会

    这是一个bug,在github上有提到:https://github.com/scrapy/scrapy/issues/428,但貌似没有完全修复,修改一下名字就好了(当然scrapy.cfgsettings.py里面也需要修改)

    2. 为每个pipeline配置spider

    上面我们是在settings.py里面配置pipeline,这里的配置的pipeline会作用于所有的spider,我们可以为每一个spider配置不同的pipeline,设置Spidercustom_settings对象

    3. 获取提取链接的节点信息

    通过LinkExtractor提取的scrapy.Link默认不带节点信息,有时候我们需要节点的其他attribute属性,scrapy.Link有个text属性保存从节点提取的text值,我们可以通过修改lxmlhtml._collect_string_content变量为etree.tostring,这样可以在提取节点值就变味渲染节点scrapy.Link.text,然后根据scrapy.Link.text属性拿到节点的html,最后提取出我们需要的值

    4. 从数据库中读取urls

    有时候我们已经把urls下载到数据库了,而不是在start_urls里配置,这时候可以重载spider的start_requests方法

    我们还可以在Request添加元数据,然后在response中访问

    5. 如何进行循环爬取

    有时候我们需要爬取的一些经常更新的页面,例如:间隔时间为2s,爬去一个列表前10页的数据,从第一页开始爬,爬完成后重新回到第一页

    目前的思路是,通过parse方法迭代返回Request进行增量爬取,由于scrapy默认由缓存机制,需要修改

    6. 关于去重

    scrapy默认有自己的去重机制,默认使用scrapy.dupefilters.RFPDupeFilter类进行去重,主要逻辑如下

    默认的去重指纹是sha1(method + url + body + header),这种方式并不能过滤很多,例如有一些请求会加上时间戳的,基本每次都会不同,这时候我们需要自定义过滤规则

    配置setting

    7. 如何在Pipeline中处理不同的Item

    scrapy所有的迭代出来的的Item都会经过所有的Pipeline,如果需要处理不同的Item,只能通过isinstance()方法进行类型判断,然后分别进行处理,暂时没有更好的方案

    8. url按顺序执行

    我们可以通过Request的priority控制url的请求的执行顺序,但由于网络请求的不确定性,不能保证返回也是按照顺序进行的,如果需要进行逐个url请求的话,吧url列表放在meta对象里面,在response的时候迭代返回下一个Request对象到调度器,达到顺序执行的目的,暂时没有更好的方案

    十二、总结

    scrapy虽然是最有名的python爬虫框架,但是还是有很多不足,例如,item不能单独配置给制定的pipeline,每一个爬取的所有item都会走遍所有的管道,需要在管道里面去判断不同类型的item,如果在pipelines和items比较多的项目,将会让项目变得非常臃肿

    十三、参考链接

  • 相关阅读:
    一行命令搞定node.js 版本升级
    doesn't contain a valid partition table 解决方法
    debian kill 进程等命令
    FastDFS配置说明(中英文)
    FastDFS问题汇总
    FastDFS常见命令
    FastDFS安装配置手册
    windows 与Linux 互传文件
    FtpClient中文乱码问题解决
    windows 配置host
  • 原文地址:https://www.cnblogs.com/ykugb/p/9795429.html
Copyright © 2011-2022 走看看