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的内存泄漏及gc模块的使用分析
Jul 16 Python
Python实现根据指定端口探测服务器/模块部署的方法
Aug 25 Python
Python删除windows垃圾文件的方法
Jul 14 Python
Python用Bottle轻量级框架进行Web开发
Jun 08 Python
Python中Scrapy爬虫图片处理详解
Nov 29 Python
学习python中matplotlib绘图设置坐标轴刻度、文本
Feb 07 Python
便捷提取python导入包的属性方法
Oct 15 Python
python存储16bit和32bit图像的实例
Dec 05 Python
Python装饰器语法糖
Jan 02 Python
Opencv+Python实现图像运动模糊和高斯模糊的示例
Apr 11 Python
pandas通过字典生成dataframe的方法步骤
Jul 23 Python
python 的 openpyxl模块 读取 Excel文件的方法
Sep 09 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
调用WordPress函数统计文章访问量及PHP原生计数器的实现
2016/03/21 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
在JavaScript中使用inline函数的问题
2007/03/08 Javascript
javascript实现上传图片前的预览(TX的面试题)
2007/08/20 Javascript
js实现宇宙星空背景效果的方法
2015/03/03 Javascript
SuperSlide标签切换、焦点图多种组合插件
2015/03/14 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
JavaScript的面向对象编程基础
2015/08/13 Javascript
轻量级jQuery插件slideBox实现带底栏轮播(焦点图)代码
2016/03/28 Javascript
浅析jQuery事件之on()方法绑定多个选择器,多个事件
2016/04/27 Javascript
jquery 全选、全不选、反选效果的实现代码【推荐】
2016/05/05 Javascript
JavaScript使用递归和循环实现阶乘的实例代码
2018/08/28 Javascript
Vuerouter的beforeEach与afterEach钩子函数的区别
2018/12/26 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
微信小程序配置服务器提示验证token失败的解决方法
2019/04/03 Javascript
vue-router之解决addRoutes使用遇到的坑
2020/07/19 Javascript
[54:57]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第二场 1月8日
2021/03/11 DOTA
python 实现登录网页的操作方法
2018/05/11 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
python excel转换csv代码实例
2019/08/26 Python
Python使用Turtle库绘制一棵西兰花
2019/11/23 Python
Python Numpy库常见用法入门教程
2020/01/16 Python
Python中常用的高阶函数实例详解
2020/02/21 Python
Python + opencv对拍照得到的图片进行背景去除的实现方法
2020/11/18 Python
在pycharm创建scrapy项目的实现步骤
2020/12/01 Python
html5 视频播放解决方案
2016/11/06 HTML / CSS
荷兰的时尚市场:To Be Dressed
2019/05/06 全球购物
艺术设计专业求职自荐信
2014/05/19 职场文书
涉密人员保密承诺书
2014/05/28 职场文书
大学新闻系求职信
2014/06/03 职场文书
敬老院献爱心活动总结
2014/07/08 职场文书
2014年绩效考核工作总结
2014/12/11 职场文书
创业计划书之美容店
2019/09/16 职场文书
React Fragment介绍与使用详解
2021/11/11 Javascript
SpringBoot项目部署到阿里云服务器的实现步骤
2022/06/28 Java/Android
MySQL 原理与优化之原数据锁的应用
2022/08/14 MySQL