scrapy-redis(六):scrapy中如何定时的运行一个任务

相信开发过scrapy的朋友对scrapy终端的日志输出非常熟悉,它会间隔一段时间输出抓取的状态,比如最近60秒内,抓取了几个网页,成功获取到了几个item。这些对于我们观察spider的运行是非常有用的,我们可以观测spider的抓取情况,速度是否在预期之中等等。

有时候,我们也需要自定义一个extension,用来定时的收集scrapy的stats,然后利用这些stats进行绘制图形,这样我们就可以图形化的去监控爬虫的状态,而不是盯着log日志。

比如,我们想自定义一个extension,每隔60秒就收集一次当前spider的stats,那我们该如何操作呢?原理其实非常的简单,就是利用scrapy中的signals和twisted中的LoopingCall。代码实现如下:

class MyCustomStatsExtension(object):
    """
    这个extension专门用来定期搜集一次stats
    """
    def __init__(self, stats):
        self.stats = stats
        self.time = 60.0

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        instance = cls(crawler.stats)
        crawler.signals.connect(instance.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(instance.spider_closed, signal=signals.spider_closed)
        return instance

    def spider_opened(self):
        self.tsk = task.LoopingCall(self.collect)
        self.tsk.start(self.time, now=True)

    def spider_closed(self):        
        if self.tsk.running:
            self.tsk.stop()

    def collect(self):
        #这里收集stats并写入相关的储存。
        #目前展示是输出到终端
        print u'将展示收集到的数据'
        print self.stats.get_stats()

上面的代码中,我们利用类方法from_crawler定制了两个信号,第一个信号是spider_opened,这个信号会在spider打开的时候,开始一个循环调用的任务,即collect()方法。第二个信号是spider_closed,它会在spider关闭的时候,关闭这个循环调用的任务。

那这个任务是如何建立的呢?twisted.internet中有一个LoopingCall()类,我们传递一个函数进去,就初始化了一个任务,然后调用其start()方法,并传入调用的时间间隔,就可以开启这个任务了。然后,在spider运行的期间,每隔一段时间,就会调用一次这个任务。在本例中,我们的任务就是收集spider的stats,用于统计绘制图形。而对于我们需要收集哪些数据,我们也可以进行定制,核心入口就是from_crawler.

你可能感兴趣的:(scrapy)