Scrapy 擴展:解決scrapy-redis 調度空跑問題

一:前言

正常情況下使用scrapy-redis 做分布式使用,這個比較方便簡單,但是有個問題:當redis調度隊列中沒有新增request 也不會讓spider停止。如果只是使用少量爬蟲服務器那還不會影響太大,如果爬蟲用的服務器很多,這將造成大量資源的浪費,并且影響服務器上其他爬蟲的速度。整理了一下資源記錄一下,方便使用。

二:解決方案

Scrapy 中有個信號工具可以幫助解決這個問題。利用信號中的 spider_idle

spider_idle

當spider進入空閑(idle)狀態(tài)時該信號被發(fā)送。空閑意味著:

  • requests正在等待被下載
  • requests被調度
  • items正在item pipeline中被處理

一旦空閑就會發(fā)送該信號,所以我們就收集這個信號,當空閑時間達到我們的設定值就會讓spider停止。

三:實例代碼

scrapy_redis_extension.py

# -*- coding: utf-8 -*-
import logging
import time
from scrapy import signals


class 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就是時間片的數(shù)量
        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環(huán)境里面,比如 /Anaconda3\Lib\site-packages,這樣再使用的時候就非常方便了。需要用的時候就在設置里面設置一個最大空閑時間,如果沒有設置默認就是10分鐘,然后 EXTENSIONS 擴展里面加入這個包的引入
setting.py 修改如下:

# redis 空跑時間 秒
IDLE_TIME= 600

# 同時擴展里面加入這個
EXTENSIONS = {
    'scrapy_redis_extension.RedisSpiderClosedExensions': 500,
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容