Python中Scrapy爬虫图片处理详解


Posted in Python onNovember 29, 2017

下载图片

下载图片有两种方式,一种是通过 Requests 模块发送 get 请求下载,另一种是使用 Scrapy 的 ImagesPipeline 图片管道类,这里主要讲后者。

安装 Scrapy 时并没有安装图像处理依赖包 Pillow,需手动安装否则运行爬虫出错。

首先在 settings.py 中设置图片的存储路径:

IMAGES_STORE = 'D:/'

图片处理相关的选项还有:

# 图片最小高度和宽度设置,可以过滤太小的图片
IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110

# 生成缩略图选项
IMAGES_THUMBS = {
 'small': (50, 50),
 'big': (270, 270),
}

之前已经存在提取内容的 TuchongPipeline 类,如果使用 ImagePipeline 可以将提取内容的操作都合并过来,但是为了更好的说明图片管道的作用,我们再单独创建一个 ImagePipeline 类,加到 pipelines.py 文件中,同时重载函数 get_media_requests:

class PhotoGalleryPipeline(object):
 ...

class PhotoPipeline(ImagesPipeline):
 def get_media_requests(self, item, info):
  for (id, url) in item['images'].items():
   yield scrapy.Request(url)

上篇文章中我们把图片的URL保存在了 item['images'] 中,它是一个字典类型的数组,形如:[{img_id: img_url}, ...],此函数中需要把 img_url 取出并构建为 scrapy.Request 请求对象并返回,每一个请求都将触发一次下载图片的操作。

到 settings.py 中注册 PhotoPipeline,并把优先级设的比提取内容的管道要高一些,保证图片下载优先于内容处理,目的是如果有图片下载未成功,通过触发 DropItem 异常可以中断这一个 Item 的处理,防止不完整的数据进入下一管道:

ITEM_PIPELINES = {
 'Toutiao.pipelines.PhotoGalleryPipeline': 300,
 'Toutiao.pipelines.PhotoPipeline': 200,
}

执行爬虫 scrapy crawl photo ,如无错误,在设定的存储目录中会出现一个 full 目录,里面是下载后的图片。

文件名处理

下载的文件名是以图片URL通过 sha1 编码得到的字符,类似 0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg 不是太友好,可以通过重载 file_path 函数自定义文件名,比如可以这样保留原文件名:

...
 def file_path(self, request, response=None, info=None):
  file_name = request.url.split('/')[-1]
  return 'full/%s' % (file_name)
...

上面这样处理难免会有重名的文件被覆盖,但参数 request 中没有过多的信息,不便于对图片分类,因此可以改为重载 item_completed 函数,在下载完成后对图片进行分类操作。

函数 item_completed 的定义:

def item_completed(self, results, item, info)

参数中包含 item ,有我们抓取的所有信息,参数 results 为下载图片的结果数组,包含下载后的路径以及是否成功下载,内容如下:

[(True,
 {'checksum': '2b00042f7481c7b056c4b410d28f33cf',
 'path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg',
 'url': 'http://www.example.com/files/product1.pdf'}),
 (False,
 Failure(...))]

重载该函数将下载图片转移到分类目录中,同时关联文件路径到 item 中,保持内容与图片为一个整体:

def item_completed(self, results, item, info):
 image_paths = {x['url'].split('/')[-1]: x['path'] for ok, x in results if ok}
 if not image_paths:
  # 下载失败忽略该 Item 的后续处理
  raise DropItem("Item contains no files")
 else:
  # 将图片转移至以 post_id 为名的子目录中
  for (dest, src) in image_paths.items():
   dir = settings.IMAGES_STORE
   newdir = dir + os.path.dirname(src) + '/' + item['post_id'] + '/'
   if not os.path.exists(newdir):
    os.makedirs(newdir)
   os.rename(dir + src, newdir + dest)
 # 将保存路径保存于 item 中(image_paths 需要在 items.py 中定义)
 item['image_paths'] = image_paths
 return item

接下来在原 TuchongPipeline 类中写入数据库的操作中,通过 item['image_paths'] 路径信息写入本地图片链接。

除了 ImagesPipeline 处理图片外,还有 FilesPipeline 可以处理文件,使用方法与图片类似,事实上 ImagesPipeline 是 FilesPipeline 的子类,因为图片也是文件的一种。

Python 相关文章推荐
跟老齐学Python之深入变量和引用对象
Sep 24 Python
使用Python压缩和解压缩zip文件的教程
May 06 Python
Python原始字符串与Unicode字符串操作符用法实例分析
Jul 22 Python
python构建深度神经网络(续)
Mar 10 Python
使用python读取.text文件特定行的数据方法
Jan 28 Python
pandas实现将日期转换成timestamp
Dec 07 Python
Pytorch在dataloader类中设置shuffle的随机数种子方式
Jan 14 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
Feb 17 Python
Python环境下安装PyGame和PyOpenGL的方法
Mar 25 Python
基于Python把网站域名解析成ip地址
May 25 Python
python判断变量是否为列表的方法
Sep 17 Python
python实现三次密码验证的示例
Apr 29 Python
Python使用django框架实现多人在线匿名聊天的小程序
Nov 29 #Python
Python实现的计数排序算法示例
Nov 29 #Python
Scrapy框架CrawlSpiders的介绍以及使用详解
Nov 29 #Python
pycharm下打开、执行并调试scrapy爬虫程序的方法
Nov 29 #Python
Python快速排序算法实例分析
Nov 29 #Python
Python3学习urllib的使用方法示例
Nov 29 #Python
Python实现的选择排序算法示例
Nov 29 #Python
You might like
php实现过滤UBB代码的类
2015/03/12 PHP
redis查看连接数及php模拟并发创建redis连接的方法
2016/12/15 PHP
PHP第三方登录―QQ登录实现方法
2017/02/06 PHP
php实现的后台表格分页功能示例
2017/10/23 PHP
Yii框架安装简明教程
2020/05/15 PHP
Z-Blog中用到的js代码
2007/03/15 Javascript
js模拟弹出效果代码修正版
2008/08/07 Javascript
文本框文本自动补全效果示例分享
2014/01/19 Javascript
jQuery进行组件开发完整实例
2015/12/15 Javascript
基于jQuery实现滚动刷新效果
2017/01/09 Javascript
用原生js做单页应用
2017/01/17 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
2017/10/12 Javascript
用node撸一个监测复联4开售短信提醒的实现代码
2019/04/10 Javascript
vue的注意规范之v-if 与 v-for 一起使用教程
2019/08/04 Javascript
关于vue路由缓存清除在main.js中的设置
2019/11/06 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
[43:35]EG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[01:28]一分钟告诉你DOTA2 TI9不朽宝藏Ⅱ中有什么!
2019/07/09 DOTA
Python使用 Beanstalkd 做异步任务处理的方法
2018/04/24 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
2019/02/07 Python
浅谈Python编程中3个常用的数据结构和算法
2019/04/30 Python
python 动态迁移solr数据过程解析
2019/09/04 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
Django实现从数据库中获取到的数据转换为dict
2020/03/27 Python
python如何调用字典的key
2020/05/25 Python
在Keras中实现保存和加载权重及模型结构
2020/06/15 Python
手把手教你将Flask应用封装成Docker服务的实现
2020/08/19 Python
Mytheresa美国官网:德国知名的女性奢侈品电商
2017/05/27 全球购物
大学生职业生涯规划范文
2014/01/08 职场文书
2014年庆元旦活动方案
2014/02/15 职场文书
士力架广告词
2014/03/20 职场文书
正规借条模板
2015/05/26 职场文书
爱护环境建议书
2015/09/14 职场文书
Java常用函数式接口总结
2021/06/29 Java/Android
在HTML中引入CSS的几种方式介绍
2021/12/06 HTML / CSS
Redis配置外网可访问(redis远程连接不上)的方法
2022/12/24 Redis