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