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 相关文章推荐
Flask入门教程实例:搭建一个静态博客
Mar 27 Python
flask + pymysql操作Mysql数据库的实例
Nov 13 Python
python 获取指定文件夹下所有文件名称并写入列表的实例
Apr 23 Python
纯用NumPy实现神经网络的示例代码
Oct 24 Python
Python中xml和json格式相互转换操作示例
Dec 05 Python
Python实现查找最小的k个数示例【两种解法】
Jan 08 Python
10分钟教你用python动画演示深度优先算法搜寻逃出迷宫的路径
Aug 12 Python
关于jupyter打开之后不能直接跳转到浏览器的解决方式
Apr 13 Python
Python用5行代码实现批量抠图的示例代码
Apr 14 Python
端午节将至,用Python爬取粽子数据并可视化,看看网友喜欢哪种粽子吧!
Jun 11 Python
FP-growth算法发现频繁项集——构建FP树
Jun 24 Python
Python几种酷炫的进度条的方式
Apr 11 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和AJAX创建RSS聚合器的代码
2007/03/13 PHP
PHP通过header实现文本文件下载的代码
2010/08/08 PHP
php实现编辑和保存文件的方法
2015/07/20 PHP
ThinkPHP实现生成和校验验证码功能
2017/04/28 PHP
Laravel 框架返回状态拦截代码
2019/10/18 PHP
javascript 命名空间以提高代码重用性
2008/11/13 Javascript
小型js框架veryide.librar源代码
2009/03/05 Javascript
一个可拖拽列宽表格实例演示
2012/11/26 Javascript
基于jquery的9行js轻松实现tab控件示例
2013/10/12 Javascript
javascript中数组中求最大值示例代码
2013/12/18 Javascript
javascript实现通过表格绘制颜色填充矩形的方法
2015/04/21 Javascript
浅析node连接数据库(express+mysql)
2015/11/30 Javascript
JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解
2016/05/31 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
video.js 实现视频只能后退不能快进的思路详解
2018/08/09 Javascript
Vue如何获取数据列表展示
2019/12/11 Javascript
[48:31]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第二场 12.17
2020/12/19 DOTA
python格式化字符串实例总结
2014/09/28 Python
初学Python函数的笔记整理
2015/04/07 Python
探究Python的Tornado框架对子域名和泛域名的支持
2015/05/02 Python
Django中传递参数到URLconf的视图函数中的方法
2015/07/18 Python
mac下如何将python2.7改为python3
2018/07/13 Python
在python中pandas的series合并方法
2018/11/12 Python
Python Image模块基本图像处理操作小结
2019/04/13 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
Python3 集合set入门基础
2020/02/10 Python
Python3.6 中的pyinstaller安装和使用教程
2020/03/16 Python
总结python 三种常见的内存泄漏场景
2020/11/20 Python
对CSS3选择器的研究(详解)
2016/09/16 HTML / CSS
摩托车和ATV零件、配件和服装的首选在线零售商:MotoSport
2017/12/22 全球购物
工厂门卫岗位职责
2013/11/25 职场文书
技校毕业生自荐信
2014/06/03 职场文书
2014年团队工作总结
2014/11/24 职场文书
奥巴马开学演讲观后感
2015/06/12 职场文书
《艾尔登法环》发布最新「战技」宣传片
2022/04/03 其他游戏
《现实主义勇者的王国再建记》第三弹OST全曲试听片段公开
2022/04/04 日漫