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完成FizzBuzzWhizz问题(拉勾网面试题)示例
May 05 Python
Python中MySQLdb和torndb模块对MySQL的断连问题处理
Nov 09 Python
Python3结合Dlib实现人脸识别和剪切
Jan 24 Python
python3爬取各类天气信息
Feb 24 Python
Python使用folium excel绘制point
Jan 03 Python
django admin组件使用方法详解
Jul 19 Python
python 设置xlabel,ylabel 坐标轴字体大小,字体类型
Jul 23 Python
使用Python对Dicom文件进行读取与写入的实现
Apr 20 Python
windows支持哪个版本的python
Jul 03 Python
Python爬虫回测股票的实例讲解
Jan 22 Python
python 遍历磁盘目录的三种方法
Apr 02 Python
Python中如何处理常见报错
Jan 18 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
discuz Passport 通行证 整合笔记
2008/06/30 PHP
PHP中使用strpos函数实现屏蔽敏感关键字功能
2014/08/21 PHP
PHP中substr函数字符串截取用法分析
2016/01/07 PHP
PHP序列化的四种实现方法与横向对比
2018/11/29 PHP
在线编辑器的实现原理(兼容IE和FireFox)
2007/03/09 Javascript
javascript 解析后的xml对象的读取方法细解
2009/07/25 Javascript
一些老手都不一定知道的JavaScript技巧
2014/05/06 Javascript
Javascript的闭包详解
2014/12/26 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
JS实现的打字机效果完整实例
2016/06/20 Javascript
JavaScript实现简易的天数计算器实例【附demo源码下载】
2017/01/18 Javascript
js实现3D图片展示效果
2017/03/09 Javascript
vue.js自定义组件directives的实例代码
2018/11/09 Javascript
vue-cli 目录结构详细讲解总结
2019/01/15 Javascript
详解TypeScript+Vue 插件 vue-class-component的使用总结
2019/02/18 Javascript
Node.js如何优雅的封装一个实用函数的npm包的方法
2019/04/29 Javascript
用实例解释Python中的继承和多态的概念
2015/04/27 Python
开源Web应用框架Django图文教程
2017/03/09 Python
Python中用字符串调用函数或方法示例代码
2017/08/04 Python
Python配置mysql的教程(推荐)
2017/10/13 Python
Tornado 多进程实现分析详解
2018/01/12 Python
Python3 中把txt数据文件读入到矩阵中的方法
2018/04/27 Python
Python实现快速计算词频功能示例
2018/06/25 Python
200行python代码实现2048游戏
2019/07/17 Python
Kears 使用:通过回调函数保存最佳准确率下的模型操作
2020/06/17 Python
Python 多线程C段扫描、检测 Ping扫描脚本的实现
2020/09/03 Python
蔻驰法国官网:COACH法国
2018/11/14 全球购物
静态变量和实例变量的区别
2015/07/07 面试题
中国梦演讲稿5分钟
2014/08/19 职场文书
学生实习证明模板汇总
2014/09/25 职场文书
维稳工作承诺书
2015/01/20 职场文书
上课迟到检讨书
2015/05/06 职场文书
党员反腐倡廉学习心得体会
2015/08/15 职场文书
2016年感恩父亲节活动总结
2016/04/01 职场文书
Python实现简单的猜单词
2021/06/15 Python
Redis实战之Lettuce的使用技巧详解
2022/12/24 Redis