Python中Scrapy使用ImagePipeline下载图片时,遇到301跳转导致失败,如何在下载中间件中修复?
RT,301 跳转都一个 CDN 的地址,我目前的做法是在 pipeline 中手动加入一个替换,可以完成下载:
def get_media_requests(self, item, info):
for img_url in item['imageUrlList']:
referer = item['imageTitleUrl']
img_url = img_url.replace('oldURL', 'new_CDNURL')
yield Request(img_url, meta = {'item': item,
'referer': referer})
但总感觉这样做有风险,因为 CDN 的 url 可能是变化的,我这里写死了,求指点合适的解决办法
Python中Scrapy使用ImagePipeline下载图片时,遇到301跳转导致失败,如何在下载中间件中修复?
3 回复
遇到301跳转导致图片下载失败,可以在下载中间件里处理。Scrapy默认会跟随重定向,但ImagePipeline的图片下载用的是独立的请求,有时需要手动处理。
核心思路是:在process_response方法中捕获301响应,提取重定向URL,然后返回一个新的Request对象。下面是一个可用的中间件示例:
# middlewares.py
from scrapy import Request
class ImageRedirectMiddleware:
def process_response(self, request, response, spider):
# 只处理图片请求,可以根据请求URL或meta中的标志判断
if request.meta.get('is_image_request', False) and response.status == 301:
redirect_url = response.headers.get('Location')
if redirect_url:
redirect_url = redirect_url.decode('utf-8')
# 返回一个新的Request,让调度器重新处理
return Request(redirect_url, meta=request.meta, dont_filter=True)
return response
然后在settings.py中启用这个中间件,并确保它在下载中间件列表里,优先级可以设高一点(数值小的先执行):
# settings.py
DOWNLOADER_MIDDLEWARES = {
'your_project.middlewares.ImageRedirectMiddleware': 543, # 默认数字范围是100-900,543是Scrapy重定向中间件的默认优先级
}
另外,你需要在发起图片下载请求时,给请求的meta加上标记,比如在自定义的ImagePipeline里:
# pipelines.py
from scrapy.pipelines.images import ImagesPipeline
from scrapy import Request
class CustomImagesPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
yield Request(image_url, meta={'is_image_request': True})
这样中间件就能识别出图片请求,并处理301跳转了。
总结:在下载中间件里拦截301响应,手动构造重定向请求。
这个问题不难吧。。。
301 为啥就下载失败? Scrapy 应该会自动跳转 301 吧。。

