scrapy配置爬虫关闭的条件(二)

Scrapy 没有按照配置 CLOSESPIDER_ITEMCOUNT, CLOSESPIDER_TIMEOUT 来终止爬虫的问题

在 settings 中配置了关闭爬虫的相关扩展:

CLOSESPIDER_TIMEOUT

CLOSESPIDER_ITEMCOUNT

CLOSESPIDER_PAGECOUNT

CLOSESPIDER_ERRORCOUNT

或者是在命令行运行 spider 时,用命令行参数进行了相关设置:

scrapy crawl xxxSpider -s CLOSESPIDER_ITEMCOUNT=10

scrapy crawl xxxSpider -s CLOSESPIDER_TIMEOUT=10

你会发现,爬虫并不会在爬取10个 item 之后或者是在 10秒之后停止,可以查到数据库中,可能有20几个 item 或者说设置为10秒,但直到几十秒才停止。

这是什么原因呢?

当触发 spider 关闭时,CLOSESPIDER_ITEMCOUNT 正好被定义,但由于 scrapy 的异步特性,它将完成对当前正在处理的所有 item 的爬取。因此,如果你想解析 2 个 item,但其实已经有 20 个 item 正在队列中等待处理了,那么爬虫也将完成所有 item的解析。

(参考: https://stackoverflow.com/questions/44006672/scrapy-closespider-itemcount-setting-not-working-as-expected?r=SearchResults)

 

如果一定要在确定的 n 个 item 之后关闭爬虫,可以偿试下面三种方案:

方案1:将下载并行数量改为1个(CONCURRENT_REQUESTS=1),可以在爬取n个之后,比较准确地把爬虫关闭在n个item的位置,但可能还有多出1个item,因为关闭spider时,可能还有一个item正在处理。

方案2:在 pipeline 中的 process_item() 方法中,将还未处理的 item 抛出 DropItem 异常处理掉。这种方法就是最准确地,只收集了 个item后其他 DropItem 丢弃。 

    if self.maxItemCount != 0 and self.itemCount >= self.maxItemCount:
        raise DropItem("ClOSESPIDER_ITEMCOUNT limit reached - " + str(self.maxItemCount))
    else:
        pass
方案3:判断当前爬到的 item数量是不是达到了 CLOSESPIDER_ITEMCOUNT 配置的数目,如果达到配置的数量,就 raise CloseSpider() 异常来关闭爬虫。(这种方法也无法准备地达到只收取 n 个 item 的目的。CloseSpider() 异常抛出后,爬虫还是会继续处理完正在等待的业务。)

(方案3参考:https://stackoverflow.com/questions/44566184/scrapy-spider-not-terminating-with-use-of-closespider-extension/44585423?r=SearchResults#44585423 )

(CloseSpider()异常文档链接: https://doc.scrapy.org/en/latest/topics/exceptions.html#closespider)

(DropItem() 异常文档链接: https://doc.scrapy.org/en/latest/topics/exceptions.html#DropItem)

方案3 示例代码如下:

import scrapy
from scrapy.spiders import XMLFeedSpider
from scrapy.exceptions import CloseSpider
from myspiders.items import MySpiderItem
 
class MySpiderSpider(XMLFeedSpider):
    name = "myspiders"
    allowed_domains = {"www.mysource.com"}
    start_urls = [
        "https://www.mysource.com/source.xml"
        ]
    iterator = 'iternodes'
    itertag = 'item'
    item_count = 0
 
    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(settings)
 
    def __init__(self, settings):
        self.settings = settings
 
    def parse_node(self, response, node):
        if(self.settings['CLOSESPIDER_ITEMCOUNT'] and int(self.settings['CLOSESPIDER_ITEMCOUNT']) == self.item_count):
            raise CloseSpider('CLOSESPIDER_ITEMCOUNT limit reached - ' + str(self.settings['CLOSESPIDER_ITEMCOUNT']))
        else:
            self.item_count += 1
        id = node.xpath('id/text()').extract()
        title = node.xpath('title/text()').extract()
        item = MySpiderItem()
        item['id'] = id
        item['title'] = title
 
        return item
 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值