Scrapy爬取触发数据丢失警告时如何配置失败请求重试
运行爬虫时输出的警告内容如下:
[scrapy.core.downloader.handlers.http11] WARNING: Got data loss in
If you want to process broken responses set the setting DOWNLOAD_FAIL_ON_DATALOSS = False -- This message won't be shown in further requests
这类随机触发、报错URL不固定的数据丢失问题,本质是网络传输波动导致的响应截断,重试对应请求即可解决,具体实现步骤如下:
第一步:修改项目
settings.py基础配置
添加如下配置项,关闭Scrapy默认遇到数据丢失直接丢弃请求的逻辑,让这类异常可以流转到重试环节:DOWNLOAD_FAIL_ON_DATALOSS = False该配置生效后,上述警告不会再重复打印,数据丢失的响应会被打上
dataloss标记进入下载中间件处理流程。第二步:编写自定义重试中间件,识别数据丢失场景触发自动重试
首先在settings.py中调整下载中间件配置,替换Scrapy默认的重试中间件,同时配置重试相关参数:DOWNLOADER_MIDDLEWARES = { # 禁用Scrapy默认自带的重试中间件 'scrapy.downloadermiddlewares.retry.RetryMiddleware': None, # 启用自定义重试中间件,优先级与默认重试中间件保持一致即可 'your_project.middlewares.DataLossRetryMiddleware': 550, } # 单请求最大重试次数,可根据自身网络环境调整 RETRY_TIMES = 3 # 保留默认需要重试的HTTP错误码 RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408]注意将上述配置里的
your_project替换为自身Scrapy项目的包名,也就是存放settings.py、middlewares.py的文件夹名称。打开项目下的
middlewares.py文件,添加自定义重试中间件的实现代码:from scrapy.downloadermiddlewares.retry import RetryMiddleware from scrapy.utils.response import response_status_message class DataLossRetryMiddleware(RetryMiddleware): def process_response(self, request, response, spider): # 识别被标记为数据丢失的响应,触发重试逻辑 if response.flags and 'dataloss' in response.flags: retry_reason = 'transmit_data_loss' return self._retry(request, retry_reason, spider) or response # 其余HTTP错误场景走原有重试判断逻辑 if request.meta.get('dont_retry', False): return response if response.status in self.retry_http_codes: reason = response_status_message(response.status) return self._retry(request, reason, spider) or response return response
配置完成后重新运行爬虫,所有触发数据丢失的请求会按照配置的次数自动重试,不会再出现随机请求数据缺漏的问题。
内容的提问来源于stack exchange,提问作者Vishnubly

