scrapy0.24文档解读之spider文件

这一次了将重新回顾spider文件
scrapy spider工作流程:

1以初始的URL初始化Request,设置回调函数。response,并作为参数传给该回调函数。

初始的request是通过调用 start_requests() 来获取的。读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request 

一般情况下start_requests()方法是不需要重写的,除非要对start_url进行处理:诸如循环产生批量的初始的接口,或者初次请求为post请求,否则,在命令行运行项目底端是默认走这个方法的

2在回调函数内解析返回的(网页)内容:返回 Item 对象、dict、 Request 或者一个包括三者的可迭代容器。 

下载之后,并调用设置的callback函数(向callback指定的函数传递,也可以用mate指定一个数据字典来传递)

3回调函数,使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml) 

来解析网页内容,并根据分析的数据生成item

4由spider返回的item将被存到数据库(由 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

spider的类及其属性和方法:

class scrapy.spiders.Spider
	    每个spider都是继承这个类其仅仅请求给定的 start_urls/start_requests ,
	    并根据返回的结果(resulting responses)调用spider的 parse

    name#爬虫名称,str,必须
    
    allowed_domains#默认跟踪的url必须在这个域中,下面这个方法解决长因此的问题
        禁用OffsiteMiddleware的时候可以使不在allowed_domains的URL也可以跟进
    
    start_urls#url列表
    
    custom_settings#dict,覆盖settings文件中的设置,上篇文章已经写了,[文章开始已介绍](https://blog.csdn.net/wc199422/article/details/82432752)
    
    crawler#这个参数建议看后面的
        初始化class后,由类方法 from_crawler() 设置, 并且链接了本spider实例对应的 Crawler 对象
   
    settings#上面你这个链接中也有用法
    
    logger#设置相关log配置的信息,会有专门的介绍
   
    from_crawler(crawler, *args, **kwargs)#在类的底层默认初始化了
          crawler (Crawler instance)#将绑定到爬虫的属性
          args (list) 
          kwargs (dict)
   
    start_requests()#
         未指定URL启用,使用start_url中url跑默认一次,可定制初次发送的请求比如post,
         指定URL时默认make_request_from_url()被调用创建request对象(一次性创建)
         def start_requests(self):##标准写法
             return [scrapy.FormRequest("http://www.example.com/login",formdata={'user': 'john', 'pass': 'secret'},callback=self.logged_in)]

    make_requests_from_url(url)#有start_request()就覆盖了他
       接收URL返回request对象其中包含parse()作为回调函数dont_filter自动过滤属性默认开启,默认被start_requests()调用
    
    parse(response)#不指定回调函数,默认被指定,负责处理response并返回处理的数据以及(/或)跟进的URL,必须返回一个包含 Request 及(或) Item 的可迭代的对象

    log(message[, level, component])#这个可以在setting中设置,同时他是封装了spider的logger属性实现的
       使用 scrapy.log.msg() 方法记录(log)message记录logging
       
    closed(reason)#这个方法最好写一写,不然在数据量大的可能会出现资源占用的问题
       提供了一个替代调用signals.connect()来监听 spider_closed 信号的快捷方式。关闭爬虫

	   样例:代码写的啰嗦,这里展示了使用start_request()方法覆盖start_url
	    import scrapy
	    from myproject.items import MyItem
	    class MySpider(scrapy.Spider):
	       name = 'example.com'
	       allowed_domains = ['example.com']
	       def start_requests(self):
	           yield scrapy.Request('http://www.example.com/1.html', self.parse)
	           yield scrapy.Request('http://www.example.com/2.html', self.parse)
	           yield scrapy.Request('http://www.example.com/3.html', self.parse)
	       def parse(self, response):
	           for h3 in response.xpath('//h3').extract():
	              yield MyItem(title=h3)
	           for url in response.xpath('//a/@href').extract():
	              yield scrapy.Request(url, callback=self.parse)

    scrapy也支持使用-a的方式在命令行上去为爬虫添加属性:
        scrapy crawl myspider -a category=electronics
   并在底层源码中去构造:
       import scrapy
       class MySpider(scrapy.Spider):
            name = 'myspider'
            def __init__(self, category=None, *args, **kwargs):
                super(MySpider, self).__init__(*args, **kwargs)
                self.start_urls = ['http://www.example.com/categories/%s' % category]

scrapy同时也提供了几种常用的爬虫类:#文档中那一段下面都有不用看

		CrawlSpider#我通常给他的别名叫深度爬虫类,必且下面两种导包在0.24与1.0文档中有点小区别:
		           ##实测都有效,跳进源码,貌似contrib中是爬虫初始化但没有东西,因该属于兼容,影响不大,还是使用最新的吧
		             0.24: class scrapy.contrib.spiders.CrawlSpider
		             1.0:class scrapy.spiders.CrawlSpider      
		    class scrapy.spiders.CrawlSpider#定义了一些规则(rule)来提供跟进link的方便的机制
		        rules#多个rule规则匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。按顺序匹配
		        parse_start_url(response)#该方法分析最初的返回值并必须返回一个 Item 对象或者 一个 Request 对象或者 一个可迭代的包含二者对象。类似parse

爬取规则(Crawling rules)
		    class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
		        link_extractor#定义了如何从爬取到的页面提取链接
        callback#每从link_extractor取出一条该函数被调用,此时回调函数命名应避开parse,应为crawlspider使用parse实现的
        cb_kwargs 包含传递给回调函数的参数(keyword argument)的字典。#类似mate
        follow 如果callback为None, follow 默认设置为 True ,否则默认为 False
        process_links#功能类似于dont_filter参数#是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤url
        process_request 是一个callable或string(该spider中同名的函数将会被调用)。 该规则提取到每个request时都会调用该函数。该函数必须返回一个request或者None。 (用来过滤request)
样例##process_links和process_request想改的话是要复写的
import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class MySpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com']
    rules = (
        # 提取匹配 'category.php' (但不匹配 'subsection.php') 的链接并跟进链接(没有callback意味着follow默认为True)
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

        # 提取匹配 'item.php' 的链接并使用spider的parse_item方法进行分析
        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )
    def parse_item(self, response):
        self.logger.info('Hi, this is an item page! %s', response.url)
        item = scrapy.Item()
        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()
        return item

XMLFeedSpider#xml反馈的爬虫

	class scrapy.spiders.XMLFeedSpider
	三个可供选择的迭代器:iternodes,html,xml
xml,html需先读取所有的dom在分析(性能问题),html能有效的应对错误的xml
     iterator:迭代器选择#属性,默认为iternodes,(string)
         iternodes:基于正则
         html:dom全文解析
         xml:dom全文解析	
         
     itertag:包含开始迭代的节点名的string#itertag = 'product'
     
     namepaces;由(prefix, url)组成的list,定义会被spider处理的命名的空间namespace(会被register_namespace()调用生成)可以通过itertag指定namespances
         class YourSpider(XMLFeedSpider):##实际上类似与start_url,只是这里是itertag中的参数是为命名空间例的内容指定使用用处
             namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
             itertag = 'n:url'
     
     adapt_response(response)
          可以在response被分析之前使用该函数来修改内容(body)。 该方法接受一个response并返回一个response(可以相同也可以不同)
     
     parse_node(response, selector)#解析通过命名空间限定请求的url返回的response
          当节点符合提供的标签名时(itertag)该方法被调用。 接收到的response以及相应的 Selector 作为参数传递给该方法,#有点类似parse,参数类多一个处理方法selector
    
     process_results(response, results)#为item做一个类似于标记的东西
          当spider返回结果(item或request)时该方法被调用。 设定该方法的目的是在结果返回给框架核心(framework core)之前做最后的处理, 例如设定item的ID。其接受一个结果的列表(list of results)及对应的response。 其结果必须返回一个结果的列表(list of results)(包含Item或者Request对象)。
例子:
    from scrapy import log
    from scrapy.contrib.spiders import XMLFeedSpider
    from myproject.items import TestItem
    class MySpider(XMLFeedSpider):#继承这一步
        name = 'example.com'
        allowed_domains = ['example.com']
        start_urls = ['http://www.example.com/feed.xml']
        iterator = 'iternodes' # 这是没必要的,它是默认值,改其他可以设置
        itertag = 'item'
        def parse_node(self, response, node):##就像为什么一定用parse写
            log.msg('Hi, this is a <%s> node!: %s' % (self.itertag, ''.join(node.extract())))
            item = TestItem()
            item['id'] = node.xpath('@id').extract()

CSVFeedSpider

class scrapy.contrib.spiders.CSVFeedSpider
spider除了其按行遍历每次迭代时调用的是 parse_row() 。
   delimiter在CSV文件中用于区分字段的分隔符。类型为string。 默认为 ',' (逗号)
   
   quotechar在csv文件中CSV文件中用于引用每个记录的字符串,默认为' " '
   
   headers在CSV文件中包含的用来提取字段的行的列表,(对应字段)
   
   parse_row(response, row)#row,对应的是csv的字段集合header。
      该方法接收一个response对象及一个以提供或检测出来的header为键的字典(代表每行)。
      #也接受改写在下载时候或者是item返回爬虫是。该spider中,您也可以覆盖 adapt_response 及 process_results 方法来进行预处理(pre-processing)及后(post-processing)处理。
例子:
rom scrapy.spiders import CSVFeedSpider
from myproject.items import TestItem
class MySpider(CSVFeedSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/feed.csv']
    delimiter = ';'
    quotechar = "'"
    headers = ['id', 'name', 'description']
    def parse_row(self, response, row):
        self.logger.info('Hi, this is a row!: %r', row)
        item = TestItem()
        item['id'] = row['id']
        item['name'] = row['name']
        item['description'] = row['description']
        return item

SitemapSpider##从roobt协议中提取接口并追踪

class scrapy.spiders.SitemapSpider
爬取网站时可以通过 Sitemaps 来发现爬取的URL。
其支持嵌套的sitemap,并能从 robots.txt 中获取sitemap的url
   sitemap_urls#包含您要爬取的url的sitemap的url列表(list)。
               可以指定为一个 robots.txt ,spider会从中分析并提取url。
   sitemap_rules一个包含 (regex, callback) 元组的列表(list):
         regex 是一个用于匹配从sitemap提供的url的正则表达式。 regex 可以是一个字符串或者编译的正则对象(compiled regex object)。
         callback指定了匹配正则表达式的url的处理函数。 callback 可以是一个字符串(spider中方法的名字)或者是callable。
         例:
         sitemap_rules = [('/product/', 'parse_product')]#类似cwalerspider中的rules
         规则按顺序进行匹配,之后第一个匹配才会被应用。如果您忽略该属性,sitemap中发现的所有url将会被 parse 函数处理。
   sitemap_follow:(跟进站点的列表,默认跟进所有)一个用于匹配要跟进的sitemap的正则表达式的列表(list)。其仅仅被应用在 使用 Sitemap首页文件来指向其他sitemap文件的站点。默认情况下所有的sitemap都会被跟进。
   sitemap_alternate_links:指定当一个 url 有可选的链接时,是否跟进。
         例:
         <url>
    	         <loc>http://example.com/</loc>
    	         <xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/>
        </url>
        当 sitemap_alternate_links 设置时,两个URL都会被获取。 当 sitemap_alternate_links 关闭时,只有 http://example.com/ 会被获取。默认 sitemap_alternate_links 关闭。
例子:
用特定的函数处理某些url,其他的使用另外的callback:
      from scrapy.spiders import SitemapSpide
      class MySpider(SitemapSpider):
          sitemap_urls = ['http://www.example.com/sitemap.xml']
          sitemap_rules = [
              ('/product/', 'parse_product'),
              ('/category/', 'parse_category'),
          ]
           def parse_product(self, response):
                pass # ... scrape product ...
           def parse_category(self, response):
                pass # ... scrape category ...
                
跟进 robots.txt 文件定义的sitemap并只跟进包含有 ..sitemap_shop 的url:	
        from scrapy.spiders import SitemapSpider
        class MySpider(SitemapSpider):
            sitemap_urls = ['http://www.example.com/robots.txt']
            sitemap_rules = [
                 ('/shop/', 'parse_shop'),
            ]
            sitemap_follow = ['/sitemap_shops']
            def parse_shop(self, response):
                 pass # ... scrape shop here ...
                 
在SitemapSpider中使用其他url:
    from scrapy.spiders import SitemapSpider

    class MySpider(SitemapSpider):
        sitemap_urls = ['http://www.example.com/robots.txt']
        sitemap_rules = [
           ('/shop/', 'parse_shop'),
        ]
        other_urls = ['http://www.example.com/about']
        def start_requests(self):
            requests = list(super(MySpider, self).start_requests())
            requests += [scrapy.Request(x, self.parse_other) for x in self.other_urls]
            return requests

        def parse_shop(self, response):
            pass # ... scrape shop here ...

       def parse_other(self, response):
            pass # ... scrape other here ...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值