Scrapy使用DownloaderMiddleware处理首个请求时被去重的问题咨询
问题原因
你遇到的重复拦截问题,核心是process_request方法的返回值不符合Scrapy的中间件设计规则:
Scrapy的Downloader Middleware中process_request的返回值有明确约定:
- 返回
None:代表当前中间件处理完成,请求会继续传递给后续的中间件处理,最终进入下载流程 - 返回
Request对象:代表中断当前中间件链,将返回的这个Request重新提交到调度器队列等待二次调度
你初始提交的sitemap请求已经被调度器记录过请求指纹(默认指纹计算规则不包含Host头,仅由请求方法、URL、请求体生成),中间件处理后返回的Request对象URL和原始请求完全一致,二次入队时就会被去重器判定为重复请求拦截,原始请求也因为中间件返回了Request被中断下载,最终爬虫无后续动作。
你观察到日志仅打印一次Got ...也符合这个逻辑:返回的二次请求被去重器直接拦截,没有进入Downloader Middleware流程,不会触发日志打印。
写法错误修正
你的逻辑本身没有问题,只是不需要返回修改后的request对象,直接修改传入的request对象是实时生效的,处理完成后返回None即可,修正后代码如下:
def process_request(self, request: scrapy.http.Request, spider): if "Host" in request.headers: return None host = request.url.removeprefix("https://").removeprefix("http://").split("/")[0] request.headers["Host"] = host spider.logger.info(f"Got {request}") # 仅需返回None,无需返回request return None
内容的提问来源于stack exchange,提问作者keddad
相关产品推荐
相关产品推荐

