Python Scrapy 不会重试超时连接

Posted

技术标签:

【中文标题】Python Scrapy 不会重试超时连接【英文标题】:Python Scrapy doesn't retry timeout connection 【发布时间】:2013-12-30 06:43:59 【问题描述】:

我使用了一些代理来抓取一些网站。这是我在settings.py中做的:

# Retry many times since proxies often fail
RETRY_TIMES = 10
# Retry on most error codes since proxies fail for different reasons
RETRY_HTTP_CODES = [500, 503, 504, 400, 403, 404, 408]

DOWNLOAD_DELAY = 3 # 5,000 ms of delay

DOWNLOADER_MIDDLEWARES = 
                    'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware' : None,
                    'myspider.comm.rotate_useragent.RotateUserAgentMiddleware' : 100,

                    'scrapy.contrib.downloadermiddleware.retry.RetryMiddleware': 200,
                    'myspider.comm.random_proxy.RandomProxyMiddleware': 300,

                    'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 400,
                

我还有一个代理下载中间件,它有以下方法:

def process_request(self, request, spider):
    log('Requesting url %s with proxy %s...' % (request.url, proxy))

def process_response(self, request, response, spider):
    log('Response received from request url %s with proxy %s' % (request.url, proxy if proxy else 'nil'))

def process_exception(self, request, exception, spider):
    log_msg('Failed to request url %s with proxy %s with exception %s' % (request.url, proxy if proxy else 'nil', str(exception)))
    #retry again.
    return request

由于proxy有时候不是很稳定,process_exception经常会提示很多请求失败的信息。这里的问题是失败的请求再也没有被尝试过。

如前所述,我设置了RETRY_TIMES和RETRY_HTTP_CODES设置,并且在代理中间件的process_exception方法中也返回了重试请求。

为什么 scrapy 不再重试失败请求,或者我如何确保至少尝试了我在 settings.py 中设置的 RETRY_TIMES 请求?

【问题讨论】:

【参考方案1】:

感谢 Scrapy IRC 频道 @nyov 的帮助。

'scrapy.contrib.downloadermiddleware.retry.RetryMiddleware': 200, 'myspider.comm.random_proxy.RandomProxyMiddleware': 300,

这里重试中间件首先运行,因此它会在请求到达代理中间件之前重试请求。在我的情况下,scrapy 需要代理来抓取网站,否则它将无休止地超时。

所以我颠倒了这两个下载中间件之间的优先级:

'scrapy.contrib.downloadermiddleware.retry.RetryMiddleware': 300, 'myspider.comm.random_proxy.RandomProxyMiddleware':200,

【讨论】:

【参考方案2】:

您的代理下载中间件似乎 -> process_response 没有按规则行事,因此破坏了中间件链

process_response() 应该:返回 Response 对象、返回 Request 对象或引发 IgnoreRequest 异常。

如果它返回一个响应(它可能是相同的给定响应,也可能是一个全新的响应),该响应将继续使用链中下一个中间件的 process_response() 进行处理。

...

【讨论】:

以上是关于Python Scrapy 不会重试超时连接的主要内容,如果未能解决你的问题,请参考以下文章

python2中MySQLdb加入超时及其重试功能

Nacos Config连接超时重试

python的urllib3库(http连接池)

Vagrant卡住连接超时重试

java客户端调用webservice时 连接超时知道是网络原因 ,如何重试如果不重试程序就死琐了,

使用 Serverless Aurora 时 Sequelize 连接超时,寻找增加超时持续时间或重试连接的方法