博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scrapy框架-图片下载功能
阅读量:5867 次
发布时间:2019-06-19

本文共 4256 字,大约阅读时间需要 14 分钟。

其实文件下载也差不多

前言

在日常爬取的过程中,图片下载还是挺多的,有时候可能纯粹是爬取图片,比如妹子图、动态图、表情包、封面图等,还有些时候是要进行验证码识别,所以需要用到图片下载功能。很高兴的是Scrapy为用户提供了图片下载功能,具体使用方法这里记录一下,它的逻辑是:

spider获取图片url --> 交给item进行处理 --> 然后根据setting的配置(开启图片下载以及设置路径)进行下载

具体的代码实现为:
Spider代码获取url,传递到item:

telnums = response.css('.address tr:first-child img::attr(src)').extract_first("")        loaders.add_value("image_urls", telnums)  # 企业联系电话(下载图片)

item对值进行预处理:

default_output_processor = TakeFirst()  # itemloaderimage_urls = scrapy.Field()  #item

然后根据settings.py的配置:

IMAGES_URLS_FIELD = "image_urls"  # 对应item里面设定的字段,取到图片的urlprodir = os.path.abspath(os.path.dirname(__file__))IMAGES_STORE = os.path.join(prodir,"images")  # 设置图片保存path

进行下载,即可完成下载功能。其中IMAGES_URLS_FIELD是固定写法,通过它来获取item中设定的图片url;IMAGES_STORE也是固定写法,设置图片保存路径。


这是一个坑

保存运行后得到一个报错:

Traceback (most recent call last):  File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks    current.result = callback(current.result, *args, **kw)  File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/scrapy/pipelines/media.py", line 79, in process_item    requests = arg_to_iter(self.get_media_requests(item, info))  File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/scrapy/pipelines/images.py", line 155, in get_media_requests    return [Request(x) for x in item.get(self.images_urls_field, [])]  File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/scrapy/pipelines/images.py", line 155, in 
return [Request(x) for x in item.get(self.images_urls_field, [])] File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/scrapy/http/request/__init__.py", line 25, in __init__ self._set_url(url) File "/home/ranbo/anaconda3/envs/pspiders/lib/python3.6/site-packages/scrapy/http/request/__init__.py", line 62, in _set_url raise ValueError('Missing scheme in request url: %s' % self._url)ValueError: Missing scheme in request url: h

网上查资料得知:

return [Request(x) for x in item.get(self.images_urls_field, [])]

scrapy下载图片的类传参数是list,而不是'这种str格式,在item传递的时候默认是所有数据都是list,但是之前在itemloaders加了TakeFirst:

class GxrcItemLoader(ItemLoader):    """ 广西人才网企业信息itemloader """    default_output_processor = TakeFirst()

所以才会被处理成str。


脱坑

现在只需要将它变成list即可,在item编写一个预处理的方法:

def keep_list(value):    """    scrapy的图片下载url默认处理列表list格式,str会报错        由于下方itemloaders设置了default_output_processor为TakeFirst        所以这里需要定义一个直接返回的函数来覆盖output_processor,这样就可以保持list格式    """    return value

然后在item代码里覆盖output_processor:

image_urls = scrapy.Field(output_processor=MapCompose(keep_list))

同时spider也得到解放,代码改成:

loaders.add_css("image_urls", ".address tr:first-child img::attr(src)")  # 企业联系电话(下载图片)

就可以下载图片了,而且代码风格有条理,舒服。


文件名和路径

下载后要获得图片的文件名和存放路径,毕竟下载完了之后不能不管。

scrapy下载的时候默认用hash加密图片url得到固定长度的值作为文件名,我要是想获得的话有两个方式,第一是自己加密图片url,生成文件名,路径就用setting里面配置的路径即可;第二个方式是重载ImagePipeline,在生成的时候就进行处理,这里演示第二种:

这个ImagePipeline写在pipelines.py文件中

它重载的是:

from scrapy.pipelines.images import ImagesPipeline

并且里面有很多的方法可以让我们在settings中进行配置,比如过滤图片的格式、图片大小等(文档有记录,以后翻文档)。

在pipelines.py文件中编写代码:

class ImagePathPipeline(ImagesPipeline):    """    继承ImagesPipeline,重载方法        以实现处理图片下载路径的目的    """    def item_completed(self, results, item, info):        pass   # (这里打断点,等下调试)

然后到settings.py中将之前使用的默认ImagesPipeline替换成自定的:

ITEM_PIPELINES = {    #'scrapy.contrib.pipeline.images.ImagesPipeline': 1,    'rspider.pipelines.ImagePathPipeline': 1,# 开启图片下载}

然后debug运行,进行调试,看看 item_completed方法里面的results是什么样的数据结构:

: [(True, {'url': 'http://vip.gxrc.com/Public/Phone/F4D1D4B0-DABB-4E83-BC54-5153BC44AA33', 'path': 'full/82cf733279ebc25c4de892e531018644e77aed67.jpg', 'checksum': 'b14c3fcdeb93209bc835d2d3dfdefb57'})]

可以看到,results是一个list,然后里面嵌套了一个tuple,再嵌套一个dict,dict存放有三个值,url/path/checksum,其中的path就是文件的路径,所以整个代码为:

class ImagePathPipeline(ImagesPipeline):    """    继承ImagesPipeline,重载item_completed方法        以实现处理图片下载路径的目的    """    def item_completed(self, results, item, info):        """ 循环results,将里面的path取出,然后赋值到item中的image_path字段,最后返回item """        for ok, value in results:            image_path = value["path"]        item["image_path"] = image_path        return item

总而言之

要给Scrapy增加图片下载功能,只需要编写Pipelines并且在Settings.py文件中开配置item中对应的图片url字段、设置图片保存地址以及开启pipeliens即可

转载地址:http://irnnx.baihongyu.com/

你可能感兴趣的文章
js判断checkbox是否选中
查看>>
多系统盘挂载
查看>>
MySQL函数怎么加锁_MYSQL 函数调用导致自动生成共享锁问题
查看>>
MR1和MR2的工作原理
查看>>
Eclipse中修改代码格式
查看>>
GRUB Legacy
查看>>
关于 error: LINK1123: failure during conversion to COFF: file invalid or corrupt 错误的解决方案...
查看>>
hexo博客解决不蒜子统计无法显示问题
查看>>
python实现链表
查看>>
java查找string1和string2是不是含有相同的字母种类和数量(string1是否是string2的重新组合)...
查看>>
Android TabActivity使用方法
查看>>
java ShutdownHook介绍与使用
查看>>
Eclipse的 window-->preferences里面没有Android选项
查看>>
《麦田里的守望者》--[美]杰罗姆·大卫·塞林格
查看>>
遇到的那些坑
查看>>
央行下属的上海资信网络金融征信系统(NFCS)签约机构数量突破800家
查看>>
[转] Lazy evaluation
查看>>
常用查找算法总结
查看>>
grep 零宽断言
查看>>
被神话的大数据——从大数据(big data)到深度数据(deep data)思维转变
查看>>