即使在收到200状态代码时重试Scrapy请求

时间:2015-02-20 23:39:02

标签: python web-scraping scrapy scrapy-spider

有一个我正在抓取的网站,有时会返回200,但在response.body中没有任何文本(当我尝试用Selector解析时会引发一个AttributeError。)

是否有一种简单的方法可以检查以确保正文包含文本,如果没有,请重试请求直到它为止?这是一些伪代码,用于概述我正在尝试做的事情。

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

基本上,有没有办法可以使用完全相同的属性(方法,网址,有效负载,Cookie等)重复请求?

2 个答案:

答案 0 :(得分:8)

关注EAFP principle

  

比获得许可更容易请求宽恕。这个常见的Python   编码风格假定存在有效的键或属性   如果假设被证明是假的,则捕获异常。这干净又快   风格的特点是存在许多尝试和除外   声明。该技术与许多人共同的LBYL风格形成鲜明对比   其他语言,如C.

处理异常,并使用dont_filter=True向当前网址提供Request

  

dont_filter(boolean) - 表示此请求不应该是   由调度程序过滤。当您想要执行时使用此选项   多次相同的请求,忽略重复过滤器。使用   它小心翼翼,否则你会陷入爬行循环。默认为False。

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

您还可以make a copy当前请求(未经测试):

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

答案 1 :(得分:4)

如何从重试中间件调用实际的_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)