使用Scrapy如何在errback触发后回到请求处理的原位置?
我来给你几个实用的方案,帮你在errback触发后重新处理出问题的那个请求(也就是你说的url[k]):
方案1:在errback里重新生成并调度原请求
这是最直接的方式,在你的errback_httpbin函数里,直接获取触发异常的原请求,然后重新调度它。你可以给请求加上重试次数限制,避免无限循环:
def errback_httpbin(failure): # 获取触发异常的原请求 request = failure.request # 读取当前重试次数,默认0 retry_count = request.meta.get('retry_count', 0) + 1 if retry_count <= 3: # *最多重试3次*,可根据需求调整 # 复制原请求并更新重试计数 new_request = request.copy() new_request.meta['retry_count'] = retry_count # 重新调度这个请求,相当于重新处理url[k] yield new_request else: # 超过重试次数,做日志记录或其他收尾处理 logging.error(f"请求 {request.url} 重试3次仍失败,放弃处理")
当url[k]触发errback时,这段代码会自动把该请求重新丢回调度队列,实现重新处理的效果。
方案2:利用Scrapy内置的RetryMiddleware
如果你用的是Scrapy框架,其实不用自己写errback的重试逻辑——Scrapy自带了重试中间件,配置一下就能自动处理异常请求的重试:
# 在settings.py中添加以下配置 RETRY_ENABLED = True # 开启重试功能 RETRY_TIMES = 3 # *最多重试3次* # 指定需要重试的HTTP状态码,可根据需求增减 RETRY_HTTP_CODES = [500, 502, 503, 504, 408, 429]
这种方式更简洁,Scrapy会自动拦截指定的异常或HTTP状态码,自动重试对应的请求,完全不用你手动在循环里处理。
方案3:手动维护待处理队列(自定义循环场景)
如果是你自己写的循环来遍历URL列表,而非依赖Scrapy的爬虫启动流程,可以维护一个待处理队列,把失败的URL重新放回队列尾部等待再次处理:
import scrapy from scrapy.crawler import CrawlerProcess import logging # 原始URL列表 urls = ["url1", "url2", "urlk", ...] # 维护一个待处理队列 pending_urls = urls.copy() class MySpider(scrapy.Spider): name = "my_spider" def start_requests(self): while pending_urls: current_url = pending_urls.pop(0) # 发起请求时携带URL和重试计数元数据 yield scrapy.Request( current_url, callback=self.parse, errback=self.errback_httpbin, meta={"url": current_url, "retry_count": 0} ) def parse(self, response): # 正常处理响应的逻辑 pass def errback_httpbin(self, failure): current_url = failure.request.meta["url"] retry_count = failure.request.meta["retry_count"] + 1 if retry_count <= 3: # 把失败的URL放回待处理队列 pending_urls.append(current_url) # 重新发起请求,更新重试计数 yield scrapy.Request( current_url, callback=self.parse, errback=self.errback_httpbin, meta={"url": current_url, "retry_count": retry_count} ) else: logging.error(f"URL {current_url} 重试3次仍失败,放弃处理") # 启动爬虫 process = CrawlerProcess() process.crawl(MySpider) process.start()
这种方式适合你完全手动控制请求分发的场景,失败的URL会被重新加入待处理队列,等待下一轮循环处理。
内容的提问来源于stack exchange,提问作者ChenJinluo
相关产品推荐
相关产品推荐

