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大牛 应该都有这份书单
Oct 31 Python
通过Python 获取Android设备信息的轻量级框架
Dec 18 Python
Python数据可视化教程之Matplotlib实现各种图表实例
Jan 13 Python
python selenium登录豆瓣网过程解析
Aug 10 Python
简单了解python中的f.b.u.r函数
Nov 02 Python
python输出数组中指定元素的所有索引示例
Dec 06 Python
python3操作注册表的方法(Url protocol)
Feb 05 Python
在脚本中单独使用django的ORM模型详解
Apr 01 Python
Python configparser模块常用方法解析
May 22 Python
使用Keras画神经网络准确性图教程
Jun 15 Python
python判断元素是否存在的实例方法
Sep 24 Python
再谈python_tkinter弹出对话框创建
Mar 20 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环境配置 php5 mysql5 apache2 phpmyadmin安装与配置
2006/11/17 PHP
关于crontab的使用详解
2013/06/24 PHP
ThinkPHP3.1新特性之G方法的使用
2014/06/19 PHP
Linux系统下php获得系统分区信息的方法
2015/03/30 PHP
[原创]php简单隔行变色功能实现代码
2016/07/09 PHP
PHP性能分析工具xhprof的安装使用与注意事项
2017/12/19 PHP
Laravel用户授权系统的使用方法示例
2018/09/16 PHP
Javascript remove 自定义数组删除方法
2009/10/20 Javascript
Js判断CSS文件加载完毕的具体实现
2014/01/17 Javascript
基于jQuery实现仿淘宝套餐选择插件
2015/03/04 Javascript
jQuery form插件的使用之处理server返回的JSON, XML,HTML数据
2016/01/26 Javascript
关于Bootstrap弹出框无法调用问题的解决办法
2016/03/10 Javascript
简单封装js的dom查询实例代码
2016/07/08 Javascript
javascript函数的四种调用模式
2017/01/08 Javascript
Bootstrap面板学习使用
2017/02/09 Javascript
BootStrap入门学习第一篇
2017/08/28 Javascript
Vue实现6位数密码效果
2018/08/18 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
RxJS在TypeScript中的简单使用详解
2020/04/13 Javascript
使用Python中的greenlet包实现并发编程的入门教程
2015/04/16 Python
python matplotlib坐标轴设置的方法
2017/12/05 Python
Python使用Phantomjs截屏网页的方法
2018/05/17 Python
Python面向对象进阶学习
2019/05/21 Python
在Python中表示一个对象的方法
2019/06/25 Python
解决django中ModelForm多表单组合的问题
2019/07/18 Python
python脚本和网页有何区别
2020/07/02 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
PyQt5的QWebEngineView使用示例
2020/10/20 Python
HTML5新特性 多线程(Worker SharedWorker)
2017/04/24 HTML / CSS
欧洲最大的婴幼儿服装及内衣公司:Petit Bateau(小帆船)
2016/08/16 全球购物
广告创意求职信
2014/03/17 职场文书
物流专业求职信
2014/06/30 职场文书
土建技术员岗位职责
2015/04/11 职场文书
环境卫生整治简报
2015/07/20 职场文书
总结Java对象被序列化的两种方法
2021/06/30 Java/Android
SpringBoot整合Minio文件存储
2022/04/03 Java/Android