如何重命名scrapy下载的图片

默认情况下,使用ImagePipeline组件下载图片的时候,图片名称是以图片URL的SHA1值进行保存的。

如:
图片URL:http://www.example.com/image.jpg

SHA1结果:3afec3b4765f8f0a07b78f98c07b83f013567a0a

则图片名称:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

但是,我想要以原来的图片名称进行保存,比如上面例子中的图片保存到本地的话,图片名称就应该是:image.jpg

stackoverflow上说是可以重写image_key函数,不过我试了下,结果发现不行,重写的image_key函数没被调用。其实不是stackoverflow上的回答是错误的,在scrapy 0.12之前,确实应该这样来解决此问题,现在scrapy的版本已经更新了很多,这个方法不适用了,下面是ImagePipeline的源码中的提醒:

ImagesPipeline.image_key(url) and file_key(url) methods are deprecated, please use file_path(request, response=None, info=None) instead

也就是说,在最新版本的Scrapy中(0.24.4),使用file_path代替image_key函数。

下面是新版本的解决方法,在scrapy 0.24.4中测试通过

  • 在pipelines.py中自定义ImagePipeline类,并重写file_path函数

    from scrapy.contrib.pipeline.images import ImagesPipeline
    from scrapy.http import Request
    from scrapy.exceptions import DropItem
    
    class MyImagesPipeline(ImagesPipeline):
        def file_path(self, request, response=None, info=None):
            image_guid = request.url.split('/')[-1]
            return 'full/%s' % (image_guid)
    
        #item['image_urls']是我们在item.py中定义的存放图片url的变量,如果定义了别的变量名,注意更换
        def get_media_requests(self, item, info):
            for image_url in item['image_urls']:
                yield Request(image_url)
    
        def item_completed(self, results, item, info):
            image_paths = [x['path'] for ok, x in results if ok]
            if not image_paths:
                raise DropItem("Item contains no images")
            return item
    
  • 修改setting.py

    ITEM_PIPELINES = {
        # 'scrapy.contrib.pipeline.images.ImagesPipeline': 1
        'sis.pipelines.MyImagesPipeline'
        }
    

可以参考stackoverflow上此问题的讨论

原文地址在这里,本文做了一些删除和修改