scrapy-redis 分布式空跑问题,数据爬完之后程序没有停下来。

问题描述:

scrapy-redis在数据爬完之后,发现根本没有停下来,程序没有结束,一直在运行。那么我们如何让它跑完之后就关闭掉呢???

如下图:

scrapy-redis 分布式空跑问题,数据爬完之后程序没有停下来。_第1张图片

 

问题分析:

在使用scrapy-redis时,redis中队列 xxx:requests 在不停执行添加与删除操作。那当xxx:requests 不存在时,说明请求的 url 可能已经结束了。

那么在正常的情况下,当队列中没有了请求,spider是不是自动关闭。

 

问题解决方案:

在scrapy 中,有一个信号叫做 spider_idle ,当spider进入空闲状态时,会自动调用它。scrapy信号链接 

功能说明如下图:

scrapy-redis 分布式空跑问题,数据爬完之后程序没有停下来。_第2张图片

那么,通过它可以知道控制爬虫的开关控制。

另外,还需要一个 scrapy 自带的 Extensions ,用它来扩展一个信号的操作,scrapy extensions 说明链接

 

问题解决思路:

通过了方案的了解,可以分析出来,当 url队列为空时,scrapy 会进入空闲状态,也就是触发spider_idle ,而且它的触发次数据是每5秒触发一次。那么我们当spider_idle触发次数超过多少,我们就可以发送信号关闭程序。

 

代码清单:

# -*- coding: utf-8 -*-

# @Time    : 2019/6/21 10:32
# @Author  : hccfm
# @File    : extensions_close.py
# @Software: PyCharm
import time

from scrapy import signals
from scrapy.exceptions import NotConfigured


class SpiderOpenCloseLogging(object):
    def __init__(self, item_count, crawler):
        """
        初始化操作
        :param item_count: 程序空闲的最大次数
        :param crawler: 类,用于发送关闭程序信号
        """
        self.item_count = item_count
        self.crawler = crawler
        self.count = 0      # 统计空闲次数
        self.idle_time = None   # 记录时间,可有可无

    @classmethod
    def from_crawler(cls, crawler):

        # 判断是否启用扩展
        if not crawler.settings.getbool('MYEXT_ENABLED'):
            raise NotConfigured

        # MYEXT_ITEMCOUNT 默认1 小时,时间单位为12次每分钟,空闲时5秒进来一次
        item_count = crawler.settings.getint('MYEXT_ITEMCOUNT', 720)

        ext = cls(item_count, 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):
        spider.log("opened spider %s" % spider.name)

    def spider_closed(self, spider):
        spider.log("closed spider %s" % spider.name)

    def spider_idle(self, spider):
        """
        记录信息,作出关闭选择
        :param spider:
        :return:
        """
        # 记录第一次进入的时间
        if self.count == 0:
            self.idle_time = time.time()

        # 判断redis_key中是否为空,如果为空时,则空闲一次,统计 + 1
        if not spider.server.exists(spider.redis_key):

            self.count += 1
        else:
            self.count = 0
        
        # 空闲超过指定分钟,结束程序
        if self.count > self.item_count:
            spider.log("spider continued idle number exceed:%s  idle datetiem exceed:%s" % (
            self.count, time.time() - self.idle_time))
            # 发送结束信号
            self.crawler.engine.close_spider(spider, 'close spider')


"""
settins.py设置

MYEXT_ENABLED = True
MYEXT_ITEMCOUNT = 360   # 半个小时
EXTENSIONS = {
   '项目名.extensions_close.SpiderOpenCloseLogging': 540,
}

"""

 

settins.py设置:

scrapy-redis 分布式空跑问题,数据爬完之后程序没有停下来。_第3张图片

 

参考文档:http://www.mamicode.com/info-detail-2225397.html

 

如有问题,欢迎指出和留言。

 

你可能感兴趣的:(爬虫部分,Python编程)