Scrapy学习篇(九)之文件与图片下载
Media Pipeline
Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的 item pipelines . 这些pipeline有些共同的方法和结构(称之为media pipeline)。我们可以使用FilesPipeline和Images Pipeline来保存文件和图片,他们有以下的一些特点:
- Files Pipeline
- 避免重新下载最近已经下载过的数据
- 指定存储路径
FilesPipeline的典型工作流程如下:
- 在一个爬虫里,你抓取一个项目,把其中图片的URL放入 file_urls 组内。
- 项目从爬虫内返回,进入项目管道。
- 当项目进入 FilesPipeline,file_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。
- 当文件下载完后,另一个字段(files)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 file_urls 组获得)和图片的校验码(checksum)。 files 列表中的文件顺序将和源 file_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 files 组中。
- Images Pipeline
- 避免重新下载最近已经下载过的数据
- 指定存储路径
- 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
- 缩略图生成
- 检测图像的宽/高,确保它们满足最小限制
和FilesPipeline类似,除了默认的字段名不同,image_urls保存图片URL地址,images保存下载后的图片信息。当然,它还提供了一些拓展功能,比如图片的缩略图,过滤图片的尺寸。
注意:你需要安装Pillow 库来实现以上的拓展功能。
启用Media Pipeline
要想使用media pipeline,你需要在设置添加一些必要的信息。
# 同时启用图片和文件管道
ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 1,'scrapy.pipelines.files.FilesPipeline': 2,}
FILES_STORE = 'D:' # 文件存储路径
IMAGES_STORE = 'D' # 图片存储路径# 避免下载最近90天已经下载过的文件内容
FILES_EXPIRES = 90
# 避免下载最近90天已经下载过的图像内容
IMAGES_EXPIRES = 30# 设置图片缩略图
IMAGES_THUMBS = {'small': (50, 50),'big': (250, 250),
}
# 图片过滤器,最小高度和宽度,低于此尺寸不下载
IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110
你可能会好奇文件的命名,在当你启用media pipeline以后,
它的默认命名方式是这样的,文件以它们URL的 SHA1 hash 作为文件名。
例如,
对下面的图片URL:http://www.example.com/image.jpg
,
其SHA1 hash 值为:3afec3b4765f8f0a07b78f98c07b83f013567a0a
将被下载并存为下面的文件:<IMAGES_STORE>/full/3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg
其中, 是定义在 IMAGES_STORE 设置里的文件夹,我们设置的是D盘,full 是用来区分图片和缩略图(如果使用的话)的一个子文件夹,这个文件夹scrapy会自动生成。
扩展Media Pipeline
下面我们以ImagesPipeline为例来自定义ImagesPipeline,需要重写以下两个方法:
get_media_requests(item, info)
在工作流程中可以看到,管道会得到图片的URL并从项目中下载。为了这么做,你需要重写 get_media_requests() 方法,并对各个图片URL返回一个Request:def get_media_requests(self, item, info):for image_url in item['image_urls']:yield scrapy.Request(image_url)
这些请求将被管道处理,当它们完成下载后,结果将以2元素的元组列表形式传送到 item_completed() 方法: 每个元组包含 (success, file_info_or_error):
- success 是一个布尔值,当图片成功下载时为 True ,因为某个原因下载失败为False
file_info_or_error 是一个包含下列关键字的字典(如果成功为 True )或者出问题时为 Twisted Failure 。
url - 文件下载的url。这是从 get_media_requests() 方法返回请求的url。
path - 图片存储的路径(类似 IMAGES_STORE)
checksum - 图片内容的 MD5 hash
item_completed() 接收的元组列表需要保证与 get_media_requests() 方法返回请求的顺序相一致。下面是 results 参数的一个典型值:[(True,{'checksum': '2b00042f7481c7b056c4b410d28f33cf','path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg','url': 'http://www.example.com/files/product1.jpg'}),(False,Failure(...))]
该方法 必须返回每一个图片的URL。
item_completed(results, items, info)
当一个单独项目中的所有图片请求完成时,例如,item里面一共有10个URL,那么当这10个URL全部下载完成以后,ImagesPipeline.item_completed() 方法将被调用。默认情况下, item_completed() 方法返回item。
使用ImagesPipeline下载图片
下面我们用上面学习到的知识来下载一些图片。
我们以http://jandan.net/ooxx为例,把页面上的图片下载下来,并产生缩略图
我们新建一个项目,名为jiandan,各个文件内容如下。
item.py
import scrapyclass JiandanItem(scrapy.Item):image_urls = scrapy.Field()#图片的链接images = scrapy.Field()
jiandan_spider.py
import scrapy
from jiandan.items import JiandanItemclass jiandanSpider(scrapy.Spider):name = 'jiandan'start_urls = ["http://jandan.net/ooxx"]def parse(self, response):item = JiandanItem()item['image_urls'] = response.xpath('//img//@src').extract() #提取图片链接yield item
settings.py
BOT_NAME = 'jiandan'SPIDER_MODULES = ['jiandan.spiders']
NEWSPIDER_MODULE = 'jiandan.spiders'DEFAULT_REQUEST_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en','User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
}ITEM_PIPELINES = {'jiandan.pipelines.JiandanPipeline':1,
}
IMAGES_STORE='H:\\jiandan'
IMAGES_THUMBS = {'small': (50, 50),'big': (200, 200),
}
pipelinse.py
import scrapy
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline #内置的图片管道class JiandanPipeline(ImagesPipeline):#继承ImagesPipeline这个类def get_media_requests(self, item, info):for image_url in item['image_urls']:image_url = "http://" + image_urlyield scrapy.Request(image_url)def item_completed(self, results, item, info):image_paths = [x['path'] for ok, x in results if ok]if not image_paths:raise DropItem("Item contains no images")return item
运行这个spider,你会发现,图片已经下载好了,如下图所示。
图片内容你可以自己慢慢看。
转载于:https://www.cnblogs.com/cnkai/p/7400467.html
Scrapy学习篇(九)之文件与图片下载相关推荐
- Scrapy之FilesPipeline和ImagesPipline文件与图片下载
Media Pipeline Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的 item pipelines . 这些pipeline有些共同的方 ...
- [网络安全学习篇60]:文件上传
引言:我的系列博客[网络安全学习篇]上线了,小编也是初次创作博客,经验不足:对千峰网络信息安全开源的视频公开课程的学习整理的笔记整理的也比较粗糙,其实看到目录有300多集的时候,讲道理,有点怂了,所以 ...
- a标签实现文件、图片下载和打开新窗口
a标签实现文件.图片下载 a标签实现文件或图片下载只需要设置 download="" 属性即可,该属性的值可以为空,如果设置值,则该值就将是文件下载的默认名字. <a her ...
- 嵌入式Linux系统编程学习之九基于文件描述符的文件操作
文章目录 前言 一.文件描述符 二.打开.创建和关闭文件 三.读写文件 四.改变文件大小 五.文件定位 六.原子操作 七.进一步理解文件描述符 八.文件描述符的复制 九.文件的锁定 十.获取文件信息 ...
- Ardunino——面向对象语言学习篇5——.h文件和.cpp文件(制作Arduino类库)
学习自:太极创客. 实践是检验真理的唯一标准,通过arduino进行实践学习C++或许是一个不错的选择. 前篇回顾 前篇学习了构造函数与析构函数,总体来说就是对象创建和消失时候要执行得函数. 前提 ...
- Scrapy学习篇(三)之创建项目
创建项目 创建项目是爬取内容的第一步,之前已经讲过,Scrapy通过scrapy startproject <project_name>命令来在当前目录下创建一个新的项目. 下面我们创建一 ...
- (转)Django ==== 实战学习篇九 在session中保存购物车
在session中保存购物车: 之前实现了产品目录的界面,用户看到合适的产品,就会加入购物车,对于购物车界面,需要考虑一下几点: 购物车应该显示:物品的清单,列出买方选中的产品: 购物车的清单有没有必 ...
- Python学习笔记九:文件I/O
打印到屏幕: 1 #!/usr/bin/python 2 3 print "Python is really a great language,", "isn't it? ...
- python学习(九)文件操作
一.文件操作简介 Python 提供了必要的函数和方法进行默认情况下的文件基本操作.你可以用 file 对象做大部分的文件操作. 1.打开文件: Python内置了一个打开文件的函数,open()函数 ...
最新文章
- VTK:Filtering之CombinePolyData
- abb机器人建立工件坐标系_ABB机器人大地坐标系修改案例
- C++-Loki Allocator
- ABAP和Java SpringBoot的单元测试
- html中js定义的方法无效,javascript中定义函数有几种常用方法?
- java并发(二):初探syncronized
- java runtime ssh 后执行指令_酒后系列:被某厂面试官吊打后酒后整理的JVM干货
- TaskTracker执行map或reduce任务的过程(二)
- Java多线程并发——CAS和AQS
- OTT系统和IPTV方案哪个更适合用于搭建局域网视频点播直播
- 初中数学抽象教学的案例_《数学核心素养“数学抽象”的实践案例研究》
- 如何将Android手机用作调制解调器; 无需生根,Redux
- ipa文件安装到ios系统
- 第二工业大学计算机应用大专录取分,二工大| 2018年上海第二工业大学专科层次依法自主招生各专业最低录取分数线...
- java实现阿里云图片文字识别
- mp3音频格式在线转换器 在线转换MP3格式
- 设计新鲜事(News Feed)系统
- 车管所免检测审车流程
- 下载源码报错Cannot connect to the Maven process. Try again later. If the problem persists, check the Maven
- docker logs使用