Scrapy使用中间件替换重定向URL为原URL后无法正确发送请求如何解决
Scrapy 自定义重定向中间件实现方案
现有代码的核心问题
你设置了dont_redirect=True后,Scrapy 自带的RedirectMiddleware不会处理3xx响应,也不会自动填充request.meta['redirect_urls']字段,所以你现有逻辑中读取跳转地址的逻辑无法生效。同时你把429限流状态码和重定向状态码混合处理,逻辑不符合实际场景。
修改后的实现代码
from urllib.parse import urljoin class CustomRedirectMiddleware: def process_request(self, request, spider): request.headers['User-Agent'] = self.ua.random def process_exception(self, request, exception, spider): return self._retry(request, spider) def _retry(self, request, spider, redirect_url=None): request.dont_filter = True # 有传入跳转地址则替换URL,否则重试原地址 if redirect_url: redirected = request.replace(url=redirect_url) redirected.dont_filter = True # 保留原请求的所有meta参数 redirected.meta.update(request.meta) return redirected return request def process_response(self, request, response, spider): # 处理重定向状态码 if response.status in [301, 302, 307]: # 从响应头Location字段获取跳转地址,处理字节解码 location = response.headers.get('Location', b'').decode('utf-8', errors='ignore') if not location: return response # 兼容相对路径跳转,拼接成绝对URL absolute_redirect_url = urljoin(response.url, location) # 传入跳转地址调用重试方法 return self._retry(request, spider, redirect_url=absolute_redirect_url) # 处理429限流,直接重试原地址 elif response.status == 429: return self._retry(request, spider) return response
配置说明
需要在项目settings.py中调整下载中间件优先级,确保你的自定义中间件在默认重定向、重试中间件之前执行,同时可以关闭默认重定向中间件避免冲突:
DOWNLOADER_MIDDLEWARES = { # 替换为你自己的中间件导入路径 '你的项目名.middlewares.CustomRedirectMiddleware': 543, # 关闭默认重定向中间件 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': None, }
注意事项
- 爬虫发起请求时携带的
meta={'dont_redirect': True,"handle_httpstatus_list": [301,302,307,429]}配置不需要修改,保持即可 - 如果需要限制重定向次数,可以在meta中新增自定义字段比如
redirect_times,每次重定向时计数,超过阈值则放弃请求避免死循环
内容的提问来源于stack exchange,提问作者MITHU
相关产品推荐
相关产品推荐

