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自动化测试之连接几组测试包实例
Sep 28 Python
Python使用matplotlib填充图形指定区域代码示例
Jan 16 Python
Django中间件工作流程及写法实例代码
Feb 06 Python
Python模拟登录的多种方法(四种)
Jun 01 Python
python Flask 装饰器顺序问题解决
Aug 08 Python
Python中使用logging和traceback模块记录日志和跟踪异常
Apr 09 Python
python SQLAlchemy的Mapping与Declarative详解
Jul 04 Python
python循环输出三角形图案的例子
Nov 22 Python
详解Django3中直接添加Websockets方式
Feb 12 Python
Python数据可视化实现多种图例代码详解
Jul 14 Python
Python中免验证跳转到内容页的实例代码
Oct 23 Python
Django自带的用户验证系统实现
Dec 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
用PHP将数据导入到Foxmail
2006/10/09 PHP
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
基于php下载文件的详解
2013/06/02 PHP
php一维二维数组键排序方法实例总结
2014/11/13 PHP
PHP读MYSQL中文乱码的快速解决方法
2016/10/01 PHP
为你的 Laravel 验证器加上多验证场景的实现
2020/04/07 PHP
Prototype最新版(1.5 rc2)使用指南(1)
2007/01/10 Javascript
鼠标经过的文本框textbox变色
2009/05/21 Javascript
Javascript 键盘事件的组合使用实现代码
2012/05/04 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
2013/04/22 Javascript
json属性名为什么要双引号(个人猜测)
2014/07/31 Javascript
JS中改变this指向的方法(call和apply、bind)
2016/03/26 Javascript
JavaScript中的原型prototype完全解析
2016/05/10 Javascript
Bootstrap 轮播(Carousel)插件
2016/12/26 Javascript
JQuery 获取多个select标签option的text内容(实例)
2017/09/07 jQuery
webpack多页面开发实践
2017/12/18 Javascript
js将键值对字符串转为json字符串的方法
2018/03/30 Javascript
jQuery实现的手动拖动控制进度条效果示例【测试可用】
2018/04/18 jQuery
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
2019/02/19 Javascript
[04:02]2014DOTA2国际邀请赛 BBC每日综述中国战队将再度登顶
2014/07/21 DOTA
Python实现的数据结构与算法之链表详解
2015/04/22 Python
Python中的pass语句使用方法讲解
2015/05/14 Python
Python探索之静态方法和类方法的区别详解
2017/10/27 Python
pandas对指定列进行填充的方法
2018/04/11 Python
浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器
2019/03/11 Python
Python实现字典按key或者value进行排序操作示例【sorted】
2019/05/03 Python
三步实现Django Paginator分页的方法
2019/06/11 Python
Python字符串的修改方法实例
2019/12/19 Python
2014年入党积极分子学习三中全会思想汇报
2014/09/13 职场文书
祖国在我心中演讲稿(小学生)
2014/09/23 职场文书
2015年调度员工作总结
2015/04/30 职场文书
退休教师追悼词
2015/06/23 职场文书
2016创先争优活动党员公开承诺书
2016/03/24 职场文书
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers
20180830晚上第一届KSL半决赛 雨神vs解冻(二龙 三炮解说)
2022/04/01 星际争霸
Win11 Beta 预览版 22621.575 和 22622.575更新补丁KB5016694发布(附更新内容大全)
2022/08/14 数码科技