• Scrapy学习笔记


    实战爬虫还是框架来的快,最近学习了下scrapy爬虫框架,总体感觉跟django一样也是一种“重型”框架,基本啥都有,填空就行,生产力也就没话说。。。

    环境搭建啥的就不赘述了,网上一大把。下面主要结合实战(爬取顶点小说网)分模块进行学习。

    步骤如下:

    1.创建工程目录 scrapy startproject Dingdian(跟django是不是一模一样。。。)

      进一步,可以直接创建一个初始网页的爬虫:scrapy genspider dingdian  http://www.23us.so/

      需要注意的是,此时的dingdian是爬虫的name,在整个项目中是唯一的,而前面创建项目的Dingdian只是个文件目录名。

    2.写items.py: 首先根据爬取数据的需求,定义数据字段,一般为了将网页解析后获取的数据进行格式化,可以将数据封装成一个Item类,然后对类进行操作。

      使用Item类时直接继承scrapy的Item类即可。scrapy只提供Field()一种字段类型,可以用来存储任意类型的数据。

    3.写爬虫最主要的部分,若先前创建了初始网页的爬虫,spider文件夹就已经有了对应的.py文件(即diangdian.py);否则,就得手动创建(文件名随意,最好跟name一致)。

      spider文件完成爬虫的主要工作,包括url的构造、requests的发出、response的操作即回调函数的编写,一般还有响应数据的解析并返回给item

      (一般使用yield返回,scrapy会根据settings的文件中的配置来传输到对应的pipeline类中。)

      其中包括html网页解析的几种方法:css选择器+xpath语法+re+bs4前两个直接用,repython自带,bs4是第三方库

    4.写pipeline.py文件,与此同时,需要在settings.py中的ITEM_PIPELINES项进行配置。

      在pipeline模块中可以实现将数据存储成json数据或者保存到mysql等数据库中。如果是图片的话,可以用scrapy自带的ImagesPipeline保存图片。

      其中,将文本数据存储成Json数据时,可以自定义Pipeline类(json.dump)实现,也可以使用scrapy提供的exporter存储Json数据。

      scrapy提供了一个JsonItemExporter类来进行Json数据的存储。需要注意的是,使用exporter生产的json数据被放在了一个列表里面。

     官方文档学习

    1.command line tool

      主要有三个功能:可以创建新的工程项目(startproject)、创建一个新的爬虫(genspider)、启动爬虫项目(crawl),

      也可以通过一些特殊命令行实现特殊的功能,如:

      scrapy fetch <url> 使用scrapy的downloader下载文件并输出到standard output上;

      scrapy parse <url> [options]  ,具体例子如  scrapy parse http://www.example.com/ -c parse_item 使用特定的回调函数对对应url返回的response进行解析。

    2. Spiders

      Spiders是一些定义了如何爬取一系列网页的类,包括如何完成爬取操作(如follow links)和如何从response的html页面中获取结构化数据(如scraping item)。

      第一步:默认情况下,start_requests()方法中需要实现向特定的URLS(由start_urls列表指出)发出Request同时其回调函数为parse()方法(默认情况)

      第二步:在回调函数中(默认为def parse()中),实现对response的解析操作,返回结构化数据的字典Item对象Request对象或者这些对象的一个迭代器。

      第三部:在回调函数中,实现对网页内容的提取,可以使用任意你喜欢的工具,如Xpath正则bs等。

      第四步:最后,一般情况下会将spider返回的items持久化在一个数据库中(通过Item Pipeline)或者写入到文件中(通过Feed exports)。

    任何编写的spider类都必须继承自scrapy.Spider类:

      这是scrapy默认捆绑的一个类,也是最最基本的spider类,其余任何自己写的类都得继承它。它不提供任何特定的功能,

      只提供一个默认的start_requests()组件(通过start_urls属性发送请求+对每个返回响应调用parse()方法进行解析)。

    属性

      name  一个字符串,定义该spider的名称,it must be unique.

      allowed_domains  一个字符串列表,包含了该spider被允许爬取的domains。即不在该列表域名及其子域名包含范围内的urls的requests是不被接受的。

                当然该属性可以通过设置项OffsiteMiddleware更改。

      start_urls  一个url的列表,列出了没指出特定的urls时该spider开始爬取的地址。该列表只是定义了“首地址”,后续爬取的urls是由解析的html中重新构造。

      custom_settings  一个用于自定义属性的字典。不常用。

      crawler  该属性通过初始化类from_crawler()设置,它将Crawler对象链接到该spider的实例被限制的对象。。(翻译的自己都看不懂了 尴尬。。。用到了再细看吧)

      settings  运行此spider时的配置。

      logger  用spider的name创建的python logger。可以通过它发送日志消息。

    方法

      from_crawler(crawler,*args,**kwargs)  该方法是Scrapy用于创建该spider时的类方法,默认配置就像是对__int__()方法的一个代理,一般不用重写此方法。

      start_requests()  该方法必须返回一个包含第一个爬取操作的Request的迭代器。当scrapy开始工作时,该方法就会被首先调用,但只会被调用一次!

               如果需要更改这种默认设置,如第一步不是爬取主页而是使用一个POST request 进行登录操作,则:       

                class MySpider(scrapy.Spider):
                    name = 'myspider'
    
                     def start_requests(self):
                        return [scrapy.FormRequest("http://www.example.com/login",
                                                   formdata={'user': 'john', 'pass': 'secret'},
                                                   callback=self.logged_in)]
    
                    def logged_in(self, response):
                        # here you would extract links to follow and return Requests for
                        # each of them, with another callback
                         pass

      parse(self, response)  该方法是scrapy中默认处理downloaded responses的回调函数。该方法(其他回调函数也一样)负责处理response,返回爬取的数据或者follow的urls。

                   该方法或者说是任意回调函数,都必须返回一个Request的迭代器或者包含数据的字典或者一个item对象。

      log(message[,level,component])  该方法一个通过scrapy的logger发送日志文件的封装。详情点击。。

      closed(reason)  当spider需要关闭时调用的方法,该方法给spider_closed信号的ignal_connect()提供了一个shortcut。

    Spider arguments

    spider的参数通过crawl命令行的-a选项进行传递。如 :scrapy crawl dingdian -a  category=electronics

    而spider可以通过__int_方法接收参数。由于__int__方法会默认调用任何spider传递进来的参数并将所有参数设置为属性值。所以可以随意调用,如self.category就等于electronics.

    需要注意的是,-a选项传递的参数是一个字符串,所以并不能直接通过参数传递start_urls(它是个列表)。

     3.Items

    Item对象是用来收集爬取数据的简单容器。它提供了一个类似字典的API,语法简单(python class),类似于django的Models。由于scrapy只有一种字段类型Filed(),所以它比django简单得多的多。

    4. Item Pipeline

    spider爬取到一个item后,它就会被送往Pipeline进行下一步处理。每个item pipeline都是一个python类,一个用于接受item并对其进行处理的类。

    item pipeline的四个典型应用是:清洗HTML数据、验证爬取的数据是否正确(与item中定义的是否一致)、检查数据是否有重复将爬取的item存储到数据库中

    自定义的pipeline是一个pyhton 类,且必须包含以下方法:

      process_item(self,item,spider)  该方法每个item pipeline的组件都得调用它,返回值为一个包含数据的字典 或 一个Item对象(或继承自Item的对象)

                       或一个Twisted Deferred 或者raise一个DropItem异常。丢弃的items就不再被其他pipeline组件处理。

                       参数:item(Item对象或字典)——爬取的item

                          spider(Spider对象)——爬取该item的spider

      open_spider(self,spider)  当spider启动时就会调用此方法。若将爬取的数据保存在文件中,可以在该方法中打开文件。

      close_spider(self,spider)  当spider关闭时就会调用此方法。若将爬取的数据保存在文件中,可以在该方法中关闭文件。  

      from_crawler(cls,crawler)  该方法用于对Crawler创建一个pipeline的实例。它必须返回一个pipeline的新实例,

                     Crawler对象可以对所有scrapy组件如settings和signals进行设置,是一种将pipeline的功能与scrapy相关联的方法。

    此外,激活一个Item Pipeline组件还需在settings的ITEM_PIPELINES项中进行设置。

    5. Feed exports

    scrapy通过Feed Exports提供对爬取item进行存储的功能,可以存储成多种序列化格式存储后端

    feed exports 默认提供四种序列化存储格式:json、json lines、CSV、XML,其他格式可以在settings的FEED_EXPORTERS项进行扩展。

      JSON   FEED_FORMAT:json

           使用的Exporter:JsonItemExporter

           注意:

      JSON lines   FEED_FORMAT:jsonlines

             使用的Exporter:JsonLinesItemExporter

      CSV   FEED_FORMAT:csv

          使用的Exporter:CsvItemExporter

          注意:因为csv使用的是固定头部,若需指定输出的列以及列的顺序需要用FEED_EXPORT_FIELDS

      XML   FEED_FORMAT:xml

           使用的Exporter:XmlItemExporter

      Pickle   FEED_FORMAT:pickle

           使用的Exporter:PickleItemExporter

      Marshal   FEED_FORMAT:marshal

           使用的Exporter:MarshalItemExporter

    6. Requests and Response

    class scrapy.http.Request(url[callback, method='GET'headersbodycookiesmetaencoding='utf-8'priority=0dont_filter=Falseerrbackflags]) 

      url——一个字符串,表示请求的目的地址url

      callback——一个可调用对象(callable),处理该请求返回响应的回调函数,默认为parse()

      method——一个字符串,该请求的HTTP方法,默认为“GET”。

      meta——一个字典,定义Request.meta属性的初始值。若给出该参数,该字典传递的值会被浅复制。

      body——str或unicode,请求的主体。无论给出的该参数是str还是unicode,甚至不给出该参数(不给出时默认为空字符串),

          最终存储的值都会是一个str类型,而不是unicode或None。所以若给出unicode,则会被自动编码成str(默认为utf-8编码)。

      headers——一个字典,该请求的头部。字典的值可以为strings(一个健只有1个值时)也可以为lists(一个键有多个值)。若定义该参数为None,HTTP则根本不会传递该参数。

      cookies——一个字典或列表,为列表格式时可以自定义cookie的domainpath属性,用于后续requests复用该cookies。大多数浏览器都会把一些网站(如购物站点)的cookies保存

           在对应站点的文件夹里,以备后续使用。但是,如果你想关闭该功能,可以在Request.meta项中设置dont_merge_cookies键的值为True即可。

      encoding——一个字符串,该请求的编码方式,默认为‘utf-8’。该编码方式用于将URL预编码和body参数传入unicode格式时转换使用。

      priority——一个整数int,该请求的优先级别(默认为0),定义了scheduler处理该请求的优先级别。优先级越高,更早被处理。负数也可以,表征相对低的优先级。

      dont_filter——布尔值,表示该请求是否会被scheduler过滤。用于重复多次发起一个完全相同的请求。默认为False。小心使用,容易陷入crawling loops。

      errback——一个可调用对象,当处理请求过程中发生任何异常时就会调用该函数,包括404异常之类的。

      flags——一个列表,传递给requests,用于登录等目的。  

    修改url、body时使用replace(),它返回一个特定参数更改而其余参数不变的request。

    replace([urlmethodheadersbodycookiesmetaencodingdont_filtercallbackerrback])

    回调函数的第一个参数是request发出的response。如 def parse1(self,response)。若想向回调函数中传递参数,需用到request的meta属性进行设置。

    Requset subclass

      class   scrapy.http.FormRequest(url[, formdata...])  

      其中formdata是一个字典,或元组的一个迭代器,包含想要传递给request的body中的被url-encoded的HTML表单数据。

      方法:from_response(response[, formname=Noneformid=Noneformnumber=0formdata=Noneformxpath=Noneformcss=Noneclickdata=Nonedont_click=False...])

      用处:1.使用FormRequest实现通过HTTP POST传递数据:

          return [FormRequest(url="http://www.example.com/post/action",
                        formdata={'name': 'John Doe', 'age': '27'},
                        callback=self.after_post)]

         2.使用FormRequest的from_response()方法模拟账户登录

          import scrapy
    
          class LoginSpider(scrapy.Spider):
              name = 'example.com'
              start_urls = ['http://www.example.com/users/login.php']
    
              def parse(self, response):
                  return scrapy.FormRequest.from_response(
                      response,
                      formdata={'username': 'john', 'password': 'secret'},
                      callback=self.after_login
                  )
    
              def after_login(self, response):
                  # check login succeed before going on
                  if "authentication failed" in response.body:
                      self.logger.error("Login failed")
                      return
                  # continue scraping with authenticated session...

                

    class scrapy.http.Response(url[, status=200headers=Nonebody=b''flags=Nonerequest=None])       

      url——该响应的url

      status——HTTP状态码,默认为200  

      headers——一个类字典对象,包含了响应的头部文件,可以使用get()方法进行获取特定键下的第一个值或者使用getlist()方法获取响应名称下的所有值。

      body——bytes,响应的主体。若想得到解码后的str文本(python3中,python2为unicode)可以使用response.text方法

      flags——同上

      request——一个请求对象,表示生产该响应的request,定义了Resposne.request的初始值。

    Response subclass

      class scrapy.http.TextResponse(url[, encoding[, ...]])

        该子类就是在基类Response上添加了编码能力。

      class scrapy.http.HtmlResponse(url[, ...])

        该类是TextResponse的子类,通过浏览 HTML 的meta http-equiv属性添加了编码自动查找功能。

      class scrapy.http.XmlResponse(url[, ...])

        该类也是TextResponse的子类。通过浏览XML的装饰行进行编码自动查找。

    7.Link Extractors

    Link Extractors对象用于仅仅为了从web pages中提取链接时使用。scrapy提供了一个scrapy.linkextractors.LinkExtractor,

    但你也可以根据自己的特定需求,创建一个简单的接口来自定义Link Extractors。

    唯一一个每个link extractor都具有的方法是extract_links,它用于接收resposne对象和返回一个scrapy.link.Link对象的列表。

    scrapy内置了一个link extractors,即scrapy.linkextractors模块:

    from scrapy.linkextractors import LinkExtractor

    默认的link extractors是LinkExtractor,不过它跟LxmlLinkExtractor一模一样。

    8.Settings

    scrapy的settings可以对所有组件进行自定义设置,包括the core、extensions、pipelines和spiders本身。

    settings配置的路径主要有以下几种:

      1.command line options命令行选项(-s 或 --set)  

         如:scrapy crawl myspider -s LOG_FILE=scrapy.log

      2.settings per-spider在每个spider单独进行设置,通过custom_settings属性

        如:class MySpider(scrapy.Spider):
              name = 'myspider'
    
              custom_settings = {
                  'SOME_SETTING': 'some value',
              }

      3.projects settings module配置该项目的settings.py文件,通常在对应spider文件中创建settings.py文件进行设置。

      4.default settings per-command命令行中通过default_settings属性进行设置

      5.default global settings对默认的全局设置进行更改,即更改scrapy.settings.default_settings模块。

    在spider中通过self.settings属性来获取属性值。

    class MySpider(scrapy.Spider):
        name = 'myspider'
        start_urls = ['http://example.com']
    
        def parse(self, response):
            print("Existing settings: %s" % self.settings.attributes.keys())

    注意,这样获取的属性值是spider初始化后的基类spider中的设置,若想在初始化之前即在spider的__init__()方法中获取,需要重写from_crawl()方法。

    class MyExtension(object):
        def __init__(self, log_is_enabled=False):
            if log_is_enabled:
                print("log is enabled!")
    
        @classmethod
        def from_crawler(cls, crawler):
            settings = crawler.settings
            return cls(settings.getbool('LOG_ENABLED'))

    9.Exceptions

    scrapy中内置的所有异常:

      exception  scrapy.exceptions.DropItem

        在item pipeline阶段使处理item中断就必须引发该异常。

      exception  scrapy.exceptions.CloseSpider(reason='cancelled')

        当发出请求的spider被关闭或停止时,回调函数中就应引发该异常,并在reason中给出原因。

      exceptionscrapy.exceptions.DontCloseSpider

      exceptionscrapy.exceptions.IgnoreRequest

      exceptionscrapy.exceptions.NotConfigured

      exceptionscrapy.exceptions.NotSupported

  • 相关阅读:
    oracle安装过程中遇到的问题
    HttpContext.Current 的缺陷
    oracle 复杂语句
    .net 中 ref out params的区别
    查看修改mysql编码方式[转载]
    Oracle 中的dual是什么东西
    KindEditor问题汇总【不定时更新】
    java中import、package作用和用法
    [笔记]: 哈弗曼树(最优二叉树) 标签: 二叉树 2017-05-17 16:38 34人阅读 评论(0) 收
    [noip 2004普及组] FBI树 标签: 二叉树递归 2017-05-17 14:29 40人阅读 评论(0)
  • 原文地址:https://www.cnblogs.com/miaoxiaonao/p/8900528.html
Copyright © 2020-2023  润新知