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实现的可以拷贝或剪切一个文件列表中的所有文件
Apr 30 Python
Python三元运算实现方法
Jan 12 Python
Python中的数据对象持久化存储模块pickle的使用示例
Mar 03 Python
Python使用functools模块中的partial函数生成偏函数
Jul 02 Python
Python多进程multiprocessing.Pool类详解
Apr 27 Python
浅谈django rest jwt vue 跨域问题
Oct 26 Python
python+pyqt5实现KFC点餐收银系统
Jan 24 Python
Python-Tkinter Text输入内容在界面显示的实例
Jul 12 Python
python3 map函数和filter函数详解
Aug 26 Python
详解Python3中的 input() 函数
Mar 18 Python
Python while true实现爬虫定时任务
Jun 08 Python
python中的错误如何查看
Jul 08 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
模拟OICQ的实现思路和核心程序(一)
2006/10/09 PHP
php完全过滤HTML,JS,CSS等标签
2009/01/16 PHP
PHP has encountered an Access Violation at 7C94BD02解决方法
2009/08/24 PHP
php echo, print, print_r, sprintf, var_dump, var_expor的使用区别
2013/06/20 PHP
PHP基于SPL实现的迭代器模式示例
2018/04/22 PHP
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
类似天猫商品详情随浏览器移动的示例代码
2014/02/27 Javascript
jquery实现背景墙聚光灯效果示例分享
2014/03/02 Javascript
jquery跟js初始化加载的多种方法及区别介绍
2014/04/02 Javascript
ie8模式下click无反应点击option无反应的解决方法
2014/10/11 Javascript
AngularJS实现表单验证
2015/01/28 Javascript
js实现彩色条纹滚动条效果
2017/03/15 Javascript
微信小程序 动态绑定事件并实现事件修改样式
2017/04/13 Javascript
ReactNative之键盘Keyboard的弹出与消失示例
2017/07/11 Javascript
详解vue-cli与webpack结合如何处理静态资源
2017/09/19 Javascript
vue代理和跨域问题的解决
2018/07/18 Javascript
在vue中使用echarts(折线图的demo,markline用法)
2020/07/20 Javascript
利用Python的Django框架中的ORM建立查询API
2015/04/20 Python
在Python的Django框架中用流响应生成CSV文件的教程
2015/05/02 Python
python对数组进行反转的方法
2015/05/20 Python
python绘制双柱形图代码实例
2017/12/14 Python
使用Python的Django和layim实现即时通讯的方法
2018/05/25 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
2018/11/07 Python
python+django+rest框架配置创建方法
2019/08/31 Python
python二维图制作的实例代码
2020/12/03 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
2020/12/07 Python
美国婚礼礼品网站:MyWeddingFavors
2018/09/26 全球购物
加拿大的标志性百货公司:Hudson’s Bay(哈得逊湾)
2019/09/03 全球购物
Java中实现多态的机制
2015/08/09 面试题
英语专业推荐信
2013/11/16 职场文书
大学新生军训感言
2014/02/25 职场文书
商务日语专业自荐信
2014/04/17 职场文书
2015年乡镇食品安全工作总结
2015/10/22 职场文书
利用JuiceFS使MySQL 备份验证性能提升 10 倍
2022/03/17 MySQL
docker compose 部署 golang 的 Athens 私有代理问题
2022/04/28 Servers
代码复现python目标检测yolo3详解预测
2022/05/06 Python