为了账号安全,请及时绑定邮箱和手机立即绑定

Scrapy 扩展:解决scrapy-redis 调度空跑问题

标签:
Redis

一:前言

正常情况下使用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 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
手记
粉丝
222
获赞与收藏
1065

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消