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 相关文章推荐
numpy 计算两个数组重复程度的方法
Nov 07 Python
python使用adbapi实现MySQL数据库的异步存储
Mar 19 Python
Python实现的服务器示例小结【单进程、多进程、多线程、非阻塞式】
May 23 Python
安装好Pycharm后如何配置Python解释器简易教程
Jun 28 Python
python flask 如何修改默认端口号的方法步骤
Jul 12 Python
讲解Python3中NumPy数组寻找特定元素下标的两种方法
Aug 04 Python
python开头的coding设置方法
Aug 08 Python
Django 自定义权限管理系统详解(通过中间件认证)
Mar 11 Python
python 使用多线程创建一个Buffer缓存器的实现思路
Jul 02 Python
Opencv python 图片生成视频的方法示例
Nov 18 Python
使用Python爬虫爬取小红书完完整整的全过程
Jan 19 Python
Pytorch 实现变量类型转换
May 17 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新手上路(三)
2006/10/09 PHP
PHP开启gzip页面压缩实例代码
2010/03/11 PHP
PHP实现图片压缩的两则实例
2014/07/19 PHP
php+ajax无刷新分页实例详解
2015/12/07 PHP
php文档工具PHP Documentor安装与使用方法
2016/01/25 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
js left,right,mid函数
2008/06/10 Javascript
SWFObject Flash js调用类
2008/07/08 Javascript
基于jQuery的试卷自动排版系统实现代码
2011/01/06 Javascript
jQuery中live方法的重复绑定说明
2011/10/21 Javascript
JavaScript 在网页上单击鼠标的地方显示层及关闭层
2012/12/30 Javascript
如何让DIV可编辑、可拖动示例代码
2013/09/18 Javascript
js库Modernizr的介绍和使用
2015/05/07 Javascript
web前端开发JQuery常用实例代码片段(50个)
2015/08/28 Javascript
使用jQuery操作HTML的table表格的实例解析
2016/03/13 Javascript
Angular 通过注入 $location 获取与修改当前页面URL的实例
2017/05/31 Javascript
vue-router 权限控制的示例代码
2017/09/21 Javascript
JS原型对象操作实例分析
2020/06/06 Javascript
js实现删除json中指定的元素
2020/09/22 Javascript
如何将Node.js中的回调转换为Promise
2020/11/10 Javascript
简介Python中用于处理字符串的center()方法
2015/05/18 Python
详解Python中映射类型的内建函数和工厂函数
2015/08/19 Python
python 字符串转列表 list 出现\ufeff的解决方法
2017/06/22 Python
在python3环境下的Django中使用MySQL数据库的实例
2017/08/29 Python
Python实现文件内容批量追加的方法示例
2017/08/29 Python
Python中常见的异常总结
2018/02/20 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
使用OpenCV获取图像某点的颜色值,并设置某点的颜色
2020/06/02 Python
python 使用elasticsearch 实现翻页的三种方式
2020/07/31 Python
用CSS3实现无限循环的无缝滚动的实例代码
2017/07/04 HTML / CSS
意大利拉斐尔时尚购物网:Raffaello Network(支持中文)
2018/11/09 全球购物
项目合作意向书模板
2014/07/29 职场文书
2015年七夕情人节活动方案
2015/05/06 职场文书
信息技术教研组工作总结
2015/08/13 职场文书
java泛型通配符详解
2021/07/25 Java/Android
MySQL中的引号和反引号的区别与用法详解
2021/10/24 MySQL