使用Scrapy自带ImagePipeline下载图片

使用Scrapy自带ImagePipeline下载图片

示例代码

# 启用scrapy自带的图片下载pipeline
ITEM_PIPELINES = {
  'scrapy.pipelines.images.ImagesPipeline': 1,
}
IMAGES_URLS_FIELD = "front_image_url"    # 设置item中作为图片下载链接的item字段
project_dir = os.path.abspath(os.path.dirname(__file__)) 
IMAGES_STORE = os.path.join(project_dir, 'images')   # 设置图片存储路径

注意

  1. 默认的ImagePipeline要求接收的图片下载url字段为列表类型,如果不是列表类型将会报错。
  2. 使用默认ImagePipeline时可能会报这样的错误:ModuleNotFoundError: No module named ‘PIL’,原因是缺少一个pillow的库,通过pip install pillow命令下载即可

遇到的异常

  1. 图片下载字段为空异常且图片下载链接不规范
    断点调试信息
    报错截图

解决方案——重载ImagePipeline

有些文章没有封面图,也就不会有图片下载链接这个值,对应的item中的该字段也就为None,但我设置的没有匹配时默认为‘ ’。但是scrapy自带的ImagePipeline是默认认位每一个item中对应的图片链接字段都有正确可访问的图片链接。导致对于一些没有该链接的item下载图片是报错异常。解决方法是自定义ImagePipeline,重写其中的get_media_request()函数,这个函数用来遍历item中的图片下载链接字段,生成request,交给scrapy引擎下载图片。我在这个方法中添加了判断是否‘ ’ 的逻辑。

class CustomImagePipeline(ImagesPipeline):  
   
	def get_media_requests(self, item, info):        
		# 重写ImagesPipeline类的get_media_requests方法        
		# 实现:下载图片之前判断item对应字段的url是否为‘ ’,如果为‘’就跳过下载。       
	    for url in item['cover_image_url']:            
	        if url != '':                
		   try:                    
		       yield Request(url=url)                
		except:                    
		       url = 'https:' + url                    
		       try:                        
			   yield Request(url=url)                    
		       except:                        
			    url = 'http:' + url                       
			    yield Request(url=url)

注意

在get_media_request()函数中生成的Request和在spider中使用的Requset是不一样的,这里的Request在from scrapy.http import Request这里,而spider中的Request在from scrapy.spider import Request

自定义ImagePipeline

示例代码

from scrapy.pipelines.images import ImagesPipeline
from scrapy.http import Request
from scrapy.exceptions import DropItem

 
class CustomImagePipeline(ImagesPipeline):

    def file_path(self, request, response=None, info=None):
        """
        重写ImagesPipeline类的file_path方法
        实现:下载下来的图片命名是以校验码来命名的,该方法实现保持原有图片命名
        :return: 图片路径
        """
        image_guid = request.url.split('/')[-1]  # 取原url的图片命名
        return 'full/%s'% image_guid

    def get_media_requests(self, item, info):
        """
        重写ImagesPipeline类的get_media_requests方法
        实现:下载图片之前判断item对应字段的url是否为‘’,如果为‘’就跳过下载。
        """
        for url in item['cover_image_url']:
            if url!= '':
                yield Request(url=url)

    def item_completed(self, results, item, info):
        """
        将图片的本地路径赋值给item['image_paths']
        :param results:下载结果,二元组定义如下:(success, image_info_or_failure)。
        第一个元素表示图片是否下载成功;第二个元素是一个字典。
        如果success=true,image_info_or_error词典包含以下键值对。失败则包含一些出错信息。
        字典内包含*url:原始URL * path:本地存储路径 * checksum:校验码
        :param item:
        :param info:
        :return:
        """
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")  # 如果没有路径则抛出异常
        item['image_paths'] = image_paths
        return item
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值