scrapy下载图片第一波
scrapy的图片管道,在ImagePipeline类中实现 ,提供了一个方便并具有额外特性的方法,来下载并本地存储图片:
* 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
* 避免重新下载最近已经下载过的图片
* 缩略图生成
* 检测图像的宽/高,确保它们满足最小的限制
这个管道也会为那些当前安排好要下载的图片保留一个内部队列,并将那些到达的包含相同图片的项目连接到那个队列中. 这可以避免多次下载几个项目共享的同一个图片.
Pillow是用来生成缩略图,并将图片归一化为JPEG/RGB格式,因此为了使用图片管道,需要安装Pillow库,不推荐PIL.
当使用图片管道 ImagePipeline,典型的工作流程如下:
* 在一个爬虫里,你抓取一个项目,把其中图片的URL放入image_urls组内.
* 项目从爬虫内返回,进入项目管道.
* 当项目进入ImagePipeline, image_urls组内的URLs将被Scrapy的调度器和下载器安排下载(这意味着调度器和中间件可以复用),当优先级更高,会在其他页面被抓取前处理. 项目会在这个特定的管道阶段保持"locker"的状态,直到完成图片的下载(或者由于某些原因未完成下载).
* 当图片下载完, 另一个组(images)将被更新到结构中,这个组将包含一个字典列表,其中包括下载图片的信息,比如下载路径,源抓取地址(从image_urls组获得)和图片的校验码. images列表中的图片顺序将和源image_urls组保持一致.如果某个图片下载失败,将会记录下错误信息,图片也不会出现在images组中.
上面的没事多读读, 下面开始实战.这里我以摄图网为例.
1.首先,修改items.py
1 import scrapy 2 3 class ImageItem(scrapy.Item): 4 image_urls = scrapy.Field() 5 images = scrapy.Field()
# image_urls和images是固定的
2. 修改settings.py ,开启你的图片管道
1 #增添如下代码 2 3 USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' 4 #开启图片管道 5 ITEM_PIPELINES = { 6 'scrapy.pipelines.images.ImagesPipeline': 1 7 } 8 #将IMAGES_STORE设置为一个有效的文件夹,用来存储下载的图片.否则管道将保持禁用状态,即使你在ITEM_PIPELINES设置中添加了它. 9 IMAGES_STORE = 'D:\\pics'
图片存储在文件中(一个图片一个文件),并使用它们URL的 SHA1 hash 作为文件名。
3. 修改pipelines.py,实现定制图片管道(这部分代码原封不动copy过去就行了)
1 from scrapy.pipelines.images import ImagesPipeline 2 from scrapy.exceptions import DropItem 3 from scrapy.http import Request 4 5 class MyImagesPipeline(ImagesPipeline): 6 def get_media_requests(self, item, info): 7 for image_url in item['image_urls']: 8 yield Request(image_url) 9 10 def item_completed(self, results, item, info): 11 image_path = [x['path'] for ok,x in results if ok] 12 if not image_path: 13 raise DropItem('Item contains no images') 14 item['image_paths'] = image_path 15 return item
4. 编写spider
1 # -*- coding: utf-8 -*- 2 import scrapy 3 from t2.items import ImageItem 4 class XiaohuaSpider(scrapy.Spider): 5 name = "baidumeinv" 6 allowed_domains = ["699pic.com"] 7 start_urls = ['http://699pic.com/people.html'] 8 download_delay = 2 9 10 def parse(self, response): 11 item = ImageItem() 12 srcs = response.xpath('//div[@class="swipeboxEx"]/div[@class="list"]/a/img/@data-original').extract() 13 item['image_urls'] = srcs 14 yield item
###这里注意一下,在settings.py存储图片,其ITEM_PIPELINES = {‘scrapy.pipelines.images.ImagesPipeline’: 1}用到的是图片的url列表,所以parse函数需要yield的是一个列表! 如果返回的是一个url字符串,则可能引发
raise ValueError('Missing scheme in request url: %s' % self._url)
ValueError: Missing scheme in request url: h
相信如果懂了上面的单个网页爬取, 那么多页爬取肯定也难不到你...
附上scrapy文档连接: https://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/images.html