scrapy 即使收到200状态代码,仍重试报废请求

pbgvytdp  于 2022-11-09  发布在  其他
关注(0)|答案(4)|浏览(239)

有一个我正在抓取的网站,有时会返回200,但没有任何文本响应。body(当我试图用Selector解析它时,引发了一个AttributeError)。
有没有一种简单的方法来检查以确保正文中包含文本,如果没有,则重试请求,直到它包含文本为止?下面是一些伪代码来概述我尝试做的事情。

def check_response(response):
    if response.body != '':
        return response
    else:
        return Request(copy_of_response.request,
                       callback=check_response)

基本上,有没有一种方法可以重复一个具有完全相同属性(方法、url、有效负载、cookie等)的请求?

lvjbypge

lvjbypge1#

遵循EAFP原则:
请求原谅比请求许可更容易。这种常见的Python编码风格假设存在有效的键或属性,并在假设被证明为错误时捕捉异常。这种干净快速的风格的特点是存在许多try和except语句。这种技术与许多其他语言(如C)常见的LBYL风格形成对比。
处理一个异常,并使用dont_filter=True向当前url生成一个Request
dont_filter(boolean)-表示排程器不应该筛选此要求。当您想要多次执行相同的要求时,可以使用此选项来忽略重复的筛选。请小心使用,否则会陷入探索循环。预设值为False。

def parse(response):
    try:
        # parsing logic here
    except AttributeError:
        yield Request(response.url, callback=self.parse, dont_filter=True)

您还可以 * 制作 * 当前请求的副本(未测试):

new_request = response.request.copy()
new_request.dont_filter = True
yield new_request

或者,使用replace()发出新请求:

new_request = response.request.replace(dont_filter=True)
yield new_request
envsm3lx

envsm3lx2#

从重试中间件调用实际的_rety()方法如何,这样它就可以作为一个正常的重试,其所有的逻辑都考虑了设置?
在设置中:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': None,
    'scraper.middlewares.retry.RetryMiddleware': 550,
}

然后,重试中间件可能如下所示:

from scrapy.downloadermiddlewares.retry import RetryMiddleware \
    as BaseRetryMiddleware

class RetryMiddleware(BaseRetryMiddleware):

    def process_response(self, request, response, spider):
        # inject retry method so request could be retried by some conditions
        # from spider itself even on 200 responses
        if not hasattr(spider, '_retry'):
            spider._retry = self._retry
        return super(RetryMiddleware, self).process_response(request, response, spider)

然后,在您的成功响应回叫中,您可以呼叫例如:

yield self._retry(response.request, ValueError, self)
iswrvxsc

iswrvxsc3#

从Scrapy 2.5.0中有一个新的方法get_retry_request()
这很简单,Scrapy文档中的示例:

def parse(self, response):
    if not response.text:
        new_request_or_none = get_retry_request(
            response.request,
            spider=self,
            reason='empty',
        )
        return new_request_or_none
tcbh2hod

tcbh2hod4#

在现有代码中,您可以简单地允许duplicate filter=True

def check_response(response):
if response.body != '':
    return response
else:
    return Request(copy_of_response.request,
                   callback=check_response, dont_filter=True)

相关问题