scrapy的圖片管道,在ImagePipeline類中實現 ,提供了一個方便並具備額外特性的方法,來下載並本地存儲圖片:html
* 將全部下載的圖片轉換成通用的格式(JPG)和模式(RGB)dom
* 避免從新下載最近已經下載過的圖片scrapy
* 縮略圖生成ide
* 檢測圖像的寬/高,確保它們知足最小的限制函數
這個管道也會爲那些當前安排好要下載的圖片保留一個內部隊列,並將那些到達的包含相同圖片的項目鏈接到那個隊列中. 這能夠避免屢次下載幾個項目共享的同一個圖片.url
Pillow是用來生成縮略圖,並將圖片歸一化爲JPEG/RGB格式,所以爲了使用圖片管道,須要安裝Pillow庫,不推薦PIL.spa
當使用圖片管道 ImagePipeline,典型的工做流程以下:code
* 在一個爬蟲裏,你抓取一個項目,把其中圖片的URL放入image_urls組內.htm
* 項目從爬蟲內返回,進入項目管道.中間件
* 當項目進入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