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 吧。。

回到顶部