刮擦 - 设置延迟以重试中间件



我正在使用Scrapy-splash,但我的内存有问题。我可以清楚地看到docker python3使用的内存正在逐渐增加,直到PC冻结。

无法弄清楚为什么它会以这种方式运行,因为我有CONCURRENT_REQUESTS=3并且没有办法 3 HTML消耗 10GB RAM。

因此,有一种解决方法可以将maxrss设置为某个合理的值。当 RAM 使用率具有此值时,docker 将重新启动,以便刷新 RAM。

但问题是,在docker关闭时,scrapy继续发送请求,因此有几个urls没有被抓取。重试中间件正在尝试立即重试这些请求,然后放弃。

[scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://www.ex.com/eiB3t/ via http://127.0.0.1:8050/execute> (failed 2 times): [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]
2019-03-30 14:28:33 [scrapy.downloadermiddlewares.retry] DEBUG: Gave up retrying <GET https://www.ex.com/eiB3t/

所以我有两个问题

  1. 你知道更好的解决方案吗?
  2. 如果没有,我怎样才能Scrapy设置为一段时间后retry请求(比如说一分钟,这样docker有时间重新启动(?

一种方法是向您的 Spider 添加一个中间件(来源,链接(:

# File: middlewares.py
from twisted.internet import reactor
from twisted.internet.defer import Deferred

class DelayedRequestsMiddleware(object):
    def process_request(self, request, spider):
        delay_s = request.meta.get('delay_request_by', None)
        if not delay_s:
            return
        deferred = Deferred()
        reactor.callLater(delay_s, deferred.callback, None)
        return deferred

你以后可以在你的蜘蛛中使用,就像这样:

import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    custom_settings = {
        'DOWNLOADER_MIDDLEWARES': {'middlewares.DelayedRequestsMiddleware': 123},
    }
    def start_requests(self):
        # This request will have itself delayed by 5 seconds
        yield scrapy.Request(url='http://quotes.toscrape.com/page/1/', 
                             meta={'delay_request_by': 5})
        # This request will not be delayed
        yield scrapy.Request(url='http://quotes.toscrape.com/page/2/')
    def parse(self, response):
        ...  # Process results here

相关方法描述如下:方法 #2

  1. 一个更复杂的解决方案可能是设置一个 Kubernetes 集群,其中运行着多个副本。这样,您可以避免仅 1 个容器的故障影响您的抓取工作。

  2. 我认为仅为重试配置等待时间并不容易。您可以使用DOWNLOAD_DELAY(但这会影响所有请求之间的延迟(,或者将RETRY_TIMES设置为比默认值 2 更高的值。

最新更新