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基于xml parse实现解析cdatasection数据
Sep 30 Python
Python HTMLParser模块解析html获取url实例
Apr 08 Python
Django中模版的子目录与include标签的使用方法
Jul 16 Python
Python中数字以及算数运算符的相关使用
Oct 12 Python
浅谈python的dataframe与series的创建方法
Nov 12 Python
python调试神器PySnooper的使用
Jul 03 Python
pandas中ix的使用详细讲解
Mar 09 Python
python numpy实现多次循环读取文件 等间隔过滤数据示例
Mar 14 Python
python json.dumps中文乱码问题解决
Apr 01 Python
Python 解决相对路径问题:"No such file or directory"
Jun 05 Python
Selenium+BeautifulSoup+json获取Script标签内的json数据
Dec 07 Python
python编写五子棋游戏
May 25 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
Zerg剧情介绍
2020/03/14 星际争霸
使用数据库保存session的方法
2006/10/09 PHP
Laravel实现ApiToken认证请求
2019/10/14 PHP
Laravel6.2中用于用户登录的新密码确认流程详解
2019/10/16 PHP
Moment.js 不容错过的超棒Javascript日期处理类库
2012/04/15 Javascript
一个简单的弹性返回顶部JS代码实现介绍
2013/06/09 Javascript
利用js读取动态网站从服务器端返回的数据
2014/02/10 Javascript
页面按钮禁用与解除禁用的方法
2014/02/19 Javascript
基于javascript实现彩票随机数生成(简单版)
2020/04/17 Javascript
浅析Javascript匿名函数与自执行函数
2016/02/06 Javascript
Bootstrap编写一个在当前网页弹出可关闭的对话框 非弹窗
2016/06/30 Javascript
JavaScript DOM 对象深入了解
2016/07/20 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
2016/08/23 Javascript
JS二分查找算法详解
2017/11/01 Javascript
Node.js上传文件功能之服务端如何获取文件上传进度
2018/02/05 Javascript
Vue安装浏览器开发工具的步骤详解
2019/05/12 Javascript
使用layui实现树形结构的方法
2019/09/20 Javascript
使用PyV8在Python爬虫中执行js代码
2017/02/16 Python
flask入门之文件上传与邮件发送示例
2018/07/18 Python
Django进阶之CSRF的解决
2018/08/01 Python
在pycharm中配置Anaconda以及pip源配置详解
2019/09/09 Python
python常用数据重复项处理方法
2019/11/22 Python
Python 远程开关机的方法
2020/11/18 Python
详解Canvas 实现炫丽的粒子运动效果(粒子生成文字)
2018/02/01 HTML / CSS
canvas线条的属性详解
2018/03/27 HTML / CSS
anello泰国官方网站:日本流行包包品牌
2019/08/08 全球购物
师范生实习的个人自我鉴定
2013/10/20 职场文书
中学运动会广播稿
2014/01/19 职场文书
大队委竞选演讲稿
2014/04/28 职场文书
党的群众路线批评与自我批评发言稿
2014/10/16 职场文书
民事和解协议书格式
2014/11/29 职场文书
教代会开幕词
2015/01/28 职场文书
2015年绩效考核工作总结
2015/05/23 职场文书
结婚十年感言
2015/07/31 职场文书
2015年秋季运动会广播稿
2015/08/19 职场文书
汽车销售合同文本
2019/08/08 职场文书