Scrapy用ImagesPipeline類提供一種方便的方式來下載和存儲圖片。html
特色:python
將下載圖片轉換成通用的JPG和RGB格式web
避免重複下載segmentfault
縮略圖生成cookie
圖片大小過濾app
當使用圖片管道 ImagePipeline,典型的工做流程以下:框架
在一個爬蟲裏,你抓取一個項目,把其中圖片的URL放入image_urls組內。dom
項目從爬蟲內返回,進入項目管道。scrapy
當項目進入ImagePipeline, image_urls組內的URLs將被Scrapy的調度器和下載器安排下載(這意味着調度器和中間件能夠複用),當優先級更高,會在其餘頁面被抓取前處理. 項目會在這個特定的管道階段保持"locker"的狀態,直到完成圖片的下載(或者因爲某些緣由未完成下載)。ide
當圖片下載完, 另外一個組(images)將被更新到結構中,這個組將包含一個字典列表,其中包括下載圖片的信息,好比下載路徑,源抓取地址(從image_urls組得到)和圖片的校驗碼. images列表中的圖片順序將和源image_urls組保持一致.若是某個圖片下載失敗,將會記錄下錯誤信息,圖片也不會出如今images組中。
項目目錄結構:
<font size=5>要想成功爬取圖片,須要通過如下幾個步驟:
class DoubanImgsItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() image_urls = Field() images = Field() image_paths = Field()
# Configure item pipelines # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html # ImagePipeline的自定義實現類 ITEM_PIPELINES = { 'douban_imgs.pipelines.DoubanImgDownloadPipeline': 300, } #設置圖片下載路徑 IMAGES_STORE = 'D:\\doubanimgs' # 過時天數 IMAGES_EXPIRES = 90 #90天內抓取的都不會被重抓
# coding=utf-8 from scrapy.spiders import Spider import re from scrapy import Request from ..items import DoubanImgsItem class download_douban(Spider): name = 'download_douban' default_headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch, br', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Host': 'www.douban.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36', } def __init__(self, url='1638835355', *args, **kwargs): self.allowed_domains = ['douban.com'] self.start_urls = [ 'http://www.douban.com/photos/album/%s/' % (url)] self.url = url # call the father base function # super(download_douban, self).__init__(*args, **kwargs) def start_requests(self): for url in self.start_urls: yield Request(url=url, headers=self.default_headers, callback=self.parse) def parse(self, response): list_imgs = response.xpath('//div[@class="photolst clearfix"]//img/@src').extract() if list_imgs: item = DoubanImgsItem() item['image_urls'] = list_imgs yield item
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html from scrapy.pipelines.images import ImagesPipeline from scrapy.exceptions import DropItem from scrapy import Request from scrapy import log class DoubanImgsPipeline(object): def process_item(self, item, spider): return item class DoubanImgDownloadPipeline(ImagesPipeline): default_headers = { 'accept': 'image/webp,image/*,*/*;q=0.8', 'accept-encoding': 'gzip, deflate, sdch, br', 'accept-language': 'zh-CN,zh;q=0.8,en;q=0.6', 'cookie': 'bid=yQdC/AzTaCw', 'referer': 'https://www.douban.com/photos/photo/2370443040/', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36', } def get_media_requests(self, item, info): for image_url in item['image_urls']: self.default_headers['referer'] = image_url yield Request(image_url, headers=self.default_headers) 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") item['image_paths'] = image_paths return item
在自定義ImagePipeline代碼中,做爲重要的是要重載get_media_requests(self, item, info)和item_completed(self, results, item, info)這兩個函數。
get_media_requests(self,item, info):
ImagePipeline根據image_urls中指定的url進行爬取,能夠經過get_media_requests爲每一個url生成一個Request。如:
for image_url in item['image_urls']: self.default_headers['referer'] = image_url yield Request(image_url, headers=self.default_headers)
item_completed(self, results, item, info):
圖片下載完畢後,處理結果會以二元組的方式返回給item_completed()函數。這個二元組定義以下:
(success, image_info_or_failure)
其中,第一個元素表示圖片是否下載成功;第二個元素是一個字典。如:
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") item['image_paths'] = image_paths return item
運行結果以下:
下載成功之後,你就會在剛纔設置的保存圖片的路徑裏看到下載完成的圖片:IMAGES_STORE = 'D:\doubanimgs'
默認狀況下,使用ImagePipeline組件下載圖片的時候,圖片名稱是以圖片URL的SHA1值進行保存的。
如:
圖片URL:http://www.example.com/image.jpg
SHA1結果:3afec3b4765f8f0a07b78f98c07b83f013567a0a
則圖片名稱:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg
若是想進行更改,請參考:使用scrapy框架的ImagesPipeline下載圖片如何保持原文件名呢?