scrapy自定義pipeline下載圖片/文件
阿新 • • 發佈:2018-12-19
自定義圖片/文件下載pipeline,自定義一個自己需要的路徑來儲存下載的圖片/文件
自定義pipeline可以基於scrapy自帶的ImagesPipeline的基礎上完成。
可以重寫ImagesPipeline中的三個法:get_media_requests(),file_path(),item_completed()
首先是在spider.py(自己的爬蟲檔案)檔案中獲取自己想要新增路徑的名字,name為自己新增的檔案路徑
item = ZhanzhangsucaispiderItem() item["name"]=response.meta["name"]#meta是以字典是的形式傳給response的. item["img_url"] = [src] yield item
然後將item返回出去,再在items.py檔案中宣告一下name, img_path是pipeline.py檔案中需要的。後邊會介紹。
class ZhanzhangsucaispiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
img_url = scrapy.Field()
img_path = scrapy.Field()
接下來修改pipeline.py檔案
import scrapy #匯入系統檔案images.py裡的ImagesPipeline類. from scrapy.pipelines.images import ImagesPipeline #DropItem是用來刪除下載圖片失敗的item的 from scrapy.exceptions import DropItem #自定義一個類,繼承於ImagesPipeline,對ImagesPipeline進行重寫,以實現自己需要的功能 class CustomImageDownloadPipleline(ImagesPipeline): #上邊說過這個三函式都是ImagesPipeline類裡的函式. def get_media_requests(self, item, info): #img_url是下載圖片的地址,存放在item(具有類似字典的功能)中, for image_url in item["img_url"]: #將下載好的圖片返回給file_path函式,圖片的儲存需要自己給他新增一個路徑,並且要給圖片起一個名字,而這些引數都在item中,file_path沒有接收item的引數,所以需要將item以字典的形式傳給meta,跟隨下載的圖片一塊傳給file_path函式. yield scrapy.Request(url=image_url,meta={"item":item}) #response=None,是因為file_path函式是用來儲存圖片的,而不是解析response的資料;官方文件中的file_path作用是將圖片的下載網址給加密,並且返回圖片下載的路徑 def file_path(self, request, response=None, info=None): #將item取出來 item = request.meta["item"] #再從item中取出分類名稱,這個name就是我們想自定義圖片路徑的檔名稱,(如果不自定義file_path函式的話,預設會將圖片下載到full檔案裡) name = item["name"] #再從item中取出img_url,分隔出來圖片的名稱.圖片的網址一般最後一個'/'後都是數字,此處用它作圖片的名字 img_url_name = item["img_url"][0].split("/")[-1] return "%s/%s"%(name,img_url_name) #專案管道里面的每一個item最終都會經過item_completd,也就是意味著有多少個item,這個item_completed函式就會被呼叫多少次。(不管下載成功,還是失敗都會被呼叫),如果不重寫該方法,item預設都會返回出去。item_completed裡面的return出去的item是經過整個專案管道處理完成之後的最終的一個item。 def item_completed(self, results, item, info): #在這通過debug可以看到results裡資料,分下載圖片成功和下載失敗兩種情況. #如果下載成功results的結果:[(True, {'url': 'http://pics.sc.chinaz.com/Files/pic/icons128/7152/f1.png', 'path': '人物頭像圖示下載/f1.png', 'checksum': 'eb7f47737a062a1525457e451c41cc99'})] #True:代表圖片下載成功 #url:圖片的地址 #path:圖片的儲存路徑 #checksum:圖片內容的 MD5 hash加密字串 #如果下載失敗results的結果:[(False, <twisted.python.failure.Failure scrapy.pipelines.files.FileException: 'NoneType' object has no attribute 'split'>)] #False:代表下載失敗 #error:下載失敗的原因 #將圖片的下載路徑取出來(資料夾名/圖片名) image_path = results[0][1].get("path") if not image_path: # 如果圖片下載失敗,則取不到image_path,那就說明對應的item是有問題的,就刪除這個item。 raise DropItem("圖片下載失敗,刪除對應的item,不讓該item返回出去。") #如果能取到img_path,說明該item是一個正常的item,可以返回出去。這個時候可以給item新增一個img_path的值,最後給這個item返回出去,這個item就是經過整個管道處理完成之後的最終的一個item。 item["img_path"]= image_path print("item_completed函式被呼叫了!") print(item) # 為什麼要renturn這個item,因為後面還有其他的管道(pipeline)會處理這個item,所以需要給它return出去。 return item
最後需要修改settings.py檔案裡的內容,第67行
ITEM_PIPELINES = {
"ZhanZhangSuCaiSpider.pipelines.CustomImageDownloadPipleline":300,
}
IMAGES_STORE = "C:/Users/Administrator/Desktop/img"
例項可以參考連結https://blog.csdn.net/cp_123321/article/details/84675034