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实现脚本锁功能(同时只能执行一个脚本)
May 10 Python
Python实现读写sqlite3数据库并将统计数据写入Excel的方法示例
Aug 07 Python
python队列通信:rabbitMQ的使用(实例讲解)
Dec 22 Python
Python使用Windows API创建窗口示例【基于win32gui模块】
May 09 Python
Python2.7.10以上pip更新及其他包的安装教程
Jun 12 Python
python 字典 按key值大小 倒序取值的实例
Jul 06 Python
用pandas中的DataFrame时选取行或列的方法
Jul 11 Python
Selenium chrome配置代理Python版的方法
Nov 29 Python
使用Django连接Mysql数据库步骤
Jan 15 Python
Python pandas用法最全整理
Aug 04 Python
python logging模块的使用
Sep 07 Python
教你利用python实现企业微信发送消息
May 23 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操作Access类(PHP+ODBC+Access)
2007/01/02 PHP
php include,include_once,require,require_once
2008/09/05 PHP
工厂模式在Zend Framework中应用介绍
2012/07/10 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
php array_udiff_assoc 计算两个数组的差集实例
2016/11/12 PHP
基于php中echo用逗号和用点号的区别详解
2018/01/23 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
php实现微信原生支付(扫码支付)功能
2018/05/30 PHP
javascript中处理时间戳为日期格式的方法
2014/01/02 Javascript
Vue.js系列之vue-router(上)(3)
2017/01/03 Javascript
Nodejs中crypto模块的安全知识讲解
2018/01/03 NodeJs
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
layerUI下的绑定事件实例代码
2018/08/17 Javascript
Vue+element-ui 实现表格的分页功能示例
2018/08/18 Javascript
微信小程序中为什么使用var that=this
2019/08/27 Javascript
Ajax获取node服务器数据的完整步骤
2020/09/20 Javascript
Python列表(list)、字典(dict)、字符串(string)基本操作小结
2014/11/28 Python
python 3利用Dlib 19.7实现摄像头人脸检测特征点标定
2018/02/26 Python
python Opencv将图片转为字符画
2021/02/19 Python
python之super的使用小结
2018/08/13 Python
详解python数据结构和算法
2019/04/18 Python
python安装本地whl的实例步骤
2019/10/12 Python
使用Tkinter制作信息提示框
2020/02/18 Python
python使用pandas抽样训练数据中某个类别实例
2020/02/28 Python
如何解决安装python3.6.1失败
2020/07/01 Python
pyqt5实现井字棋的示例代码
2020/12/07 Python
canvas三角函数模拟水波效果的示例代码
2018/07/03 HTML / CSS
劲霸男装广告词改编版
2014/03/21 职场文书
《月亮湾》教学反思
2014/04/14 职场文书
喝酒驾驶检讨书
2014/10/01 职场文书
四风问题原因分析及整改措施
2014/10/24 职场文书
机关干部四风问题自查报告及整改措施
2014/10/26 职场文书
影视后期实训报告
2014/11/05 职场文书
2015年乡镇环保工作总结
2015/04/22 职场文书
公司年会晚会开幕词
2019/04/02 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js