Scrapy框架-图片下载功能

简介: 其实文件下载也差不多前言在日常爬取的过程中,图片下载还是挺多的,有时候可能纯粹是爬取图片,比如妹子图、动态图、表情包、封面图等,还有些时候是要进行验证码识别,所以需要用到图片下载功能。

其实文件下载也差不多

前言

在日常爬取的过程中,图片下载还是挺多的,有时候可能纯粹是爬取图片,比如妹子图、动态图、表情包、封面图等,还有些时候是要进行验证码识别,所以需要用到图片下载功能。很高兴的是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()  # itemloader

image_urls = scrapy.Field()  #item

然后根据settings.py的配置:

IMAGES_URLS_FIELD = "image_urls"  # 对应item里面设定的字段,取到图片的url
prodir = 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 <listcomp>
    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,而不是'http://www.baidu.com/123.jpg'这种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是什么样的数据结构:

<class 'list'>: [(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即可

目录
相关文章
|
28天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
79 6
|
2月前
|
数据采集 中间件 开发者
Scrapy爬虫框架-自定义中间件
Scrapy爬虫框架-自定义中间件
55 1
|
2月前
|
数据采集 中间件 Python
Scrapy爬虫框架-通过Cookies模拟自动登录
Scrapy爬虫框架-通过Cookies模拟自动登录
100 0
|
5月前
|
数据采集 存储 中间件
高效数据抓取:Scrapy框架详解
高效数据抓取:Scrapy框架详解
|
29天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
57 4
|
2月前
|
数据采集 中间件 数据挖掘
Scrapy 爬虫框架(一)
Scrapy 爬虫框架(一)
50 0
|
2月前
|
数据采集 XML 前端开发
Scrapy 爬虫框架(二)
Scrapy 爬虫框架(二)
47 0
|
4月前
|
数据采集 存储 XML
Scrapy框架实现数据采集的详细步骤
本文介绍了使用Scrapy框架从宁波大学经济学院网站爬取新闻或公告详情页内容的过程,包括创建Scrapy项目、编写爬虫规则、提取所需信息,并最终将数据存储到Excel文件中的方法和步骤。
Scrapy框架实现数据采集的详细步骤
|
4月前
|
数据采集 中间件 调度
Scrapy 爬虫框架的基本使用
Scrapy 爬虫框架的基本使用
|
4月前
|
数据采集 存储 中间件
Python进行网络爬虫:Scrapy框架的实践
【8月更文挑战第17天】网络爬虫是自动化程序,用于从互联网收集信息。Python凭借其丰富的库和框架成为构建爬虫的首选语言。Scrapy作为一款流行的开源框架,简化了爬虫开发过程。本文介绍如何使用Python和Scrapy构建简单爬虫:首先安装Scrapy,接着创建新项目并定义爬虫,指定起始URL和解析逻辑。运行爬虫可将数据保存为JSON文件或存储到数据库。此外,Scrapy支持高级功能如中间件定制、分布式爬取、动态页面渲染等。在实践中需遵循最佳规范,如尊重robots.txt协议、合理设置爬取速度等。通过本文,读者将掌握Scrapy基础并了解如何高效地进行网络数据采集。
220 6