一:前言
正常情况下使用scrapy-redis 做分布式使用,这个比较方便简单,但是有个问题:当redis调度队列中没有新增request 也不会让spider停止。如果只是使用少量爬虫服务器那还不会影响太大,如果爬虫用的服务器很多,这将造成大量资源的浪费,并且影响服务器上其他爬虫的速度。整理了一下资源记录一下,方便使用。
二:解决方案
Scrapy 中有个信号工具可以帮助解决这个问题。利用信号中的 spider_idle
spider_idle
当spider进入空闲(idle)状态时该信号被发送。空闲意味着:
requests正在等待被下载
requests被调度
items正在item pipeline中被处理
一旦空闲就会发送该信号,所以我们就收集这个信号,当空闲时间达到我们的设定值就会让spider停止。
三:实例代码
scrapy_redis_extension.py
# -*- coding: utf-8 -*-import loggingimport timefrom scrapy import signalsclass RedisSpiderClosedExensions(object): def __init__(self, idle_number, crawler): self.crawler = crawler self.idle_number = idle_number self.idle_list = [] self.idle_count = 0 @classmethod def from_crawler(cls, crawler): # IDLE_NUMBER目前被被设定为等待时间,IDLE一个时间片5秒,所以setting.py中设置的时间除以5就是时间片的数量 idle_number = crawler.settings.getint('IDLE_TIME', 600) // 5 ext = cls(idle_number, crawler) crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened) crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) crawler.signals.connect(ext.spider_idle, signal=signals.spider_idle) return ext def spider_opened(self, spider): logger.info("opened spider %s redis spider Idle, Continuous idle limit: %d", spider.name, self.idle_number) def spider_closed(self, spider): logger.info("closed spider %s, idle count %d , Continuous idle count %d", spider.name, self.idle_count, len(self.idle_list)) def spider_idle(self, spider): self.idle_count += 1 self.idle_list.append(time.time()) idle_list_len = len(self.idle_list) if idle_list_len > 2 and self.idle_list[-1] - self.idle_list[-2] > 6: self.idle_list = [self.idle_list[-1]] elif idle_list_len > self.idle_number: logger.info('\n continued idle number exceed {} Times' '\n meet the idle shutdown conditions, will close the reptile operation' '\n idle start time: {}, close spider time: {}'.format(self.idle_number, self.idle_list[0], self.idle_list[0])) self.crawler.engine.close_spider(spider, 'closespider_pagecount')
五:说明
如果把这个扩展放到python环境里面,比如 /Anaconda3\Lib\site-packages,这样再使用的时候就非常方便了。需要用的时候就在设置里面设置一个最大空闲时间,如果没有设置默认就是10分钟,然后 EXTENSIONS 扩展里面加入这个包的引入
setting.py 修改如下:
# redis 空跑时间 秒IDLE_TIME= 600# 同时扩展里面加入这个EXTENSIONS = { 'scrapy_redis_extension.RedisSpiderClosedExensions': 500, }
作者:rieuse
链接:https://www.jianshu.com/p/ba010b805cea
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦