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

猜你喜欢

转载自www.cnblogs.com/miaoxiaonao/p/8900528.html