自定義圖檔/文檔下載下傳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
可以關注我的公衆号:技術趣談
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1kjMzUDO0EjM1AzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)