在之前的Scrapy學習篇(四)之數據的存儲的章節中,我們其實已經使用了Item Pipeline,那一章節主要的目的是形成一個籠統的認識,知道scrapy能幹些什麼,但是,爲了形成一個更加全面的體系,我們在這一章節中,將會單獨介紹Item Pipeline,方便以後你自定義你的item pipeline。
當Item在Spider中被收集之後,它將會被傳遞到Item Pipeline,一些組件會按照一定的順序執行對Item的處理。
每個item pipeline組件(有時稱之爲“Item Pipeline”)是實現了簡單方法的Python類。他們接收到Item並通過它執行一些行爲,同時也決定此Item是否繼續通過pipeline,或是被丟棄而不再進行處理。
以下是item pipeline的一些典型應用:
- 清理HTML數據
- 驗證爬取的數據(檢查item包含某些字段)
- 查重(並丟棄)
- 將爬取結果保存到數據庫或者文件中
編寫item pipeline
每個item pipeline組件是一個獨立的Python類,同時必須實現以下方法:
- process_item(self, item, spider)
每個item pipeline組件都需要調用該方法,這個方法必須返回一個具有數據的dict,或是 Item (或任何繼承類)對象, 或是拋出 DropItem 異常,被丟棄的item將不會被之後的pipeline組件所處理。
參數:
item (Item 對象或者一個dict) – 被爬取的item
spider (Spider 對象) – 爬取該item的spider - open_spider(self, spider)
當spider被開啓時,這個方法被調用。
參數:
spider (Spider 對象) – 被開啓的spider - close_spider(self, spider)
當spider被關閉時,這個方法被調用
參數:
spider (Spider 對象) – 被關閉的spider - from_crawler(cls, crawler)
如果給出,這個類方法將會被調用從Crawler創建一個pipeline實例,它必須返回一個pipeline的新的實例,Crawler對象提供了調用scrapy所有的核心組件的權限,比如你可以調用settings裏面的設置項。事實上,在後面的學習中,你會發現,這是非常常用的一個方法,你會經常用到。
使用Item Pipeline去重
一個用於去重的過濾器,丟棄那些已經被處理過的item。假設我們的item有一個唯一的id,但是我們spider返回的多個item中包含有相同的id,我們就可以使用集合來去重,下面是一個例子:
from scrapy.exceptions import DropItem
class DuplicatesPipeline(object):
def __init__(self):
self.ids_seen = set()
def process_item(self, item, spider):
if item['id'] in self.ids_seen:
raise DropItem("Duplicate item found: %s" % item)
else:
self.ids_seen.add(item['id'])
return item
可以看到,我們設置了一個去重集合,用來存放具有唯一性的id字段,當我們抓取的item裏面的id已經被處理過,那麼將會直接丟棄這個item,否則,就會進行後續的處理並且把這個id放入去重集合之中,達到去重的目的。
保存到文件或數據庫
具體的代碼,可以參照Scrapy學習篇(四)之數據的存儲這一章節,這裏就不在贅述。
啓用Item Pipeline組件
爲了啓用一個Item Pipeline組件,你必須將它的類添加到 ITEM_PIPELINES 配置,就像下面這個例子:
ITEM_PIPELINES = {
'myproject.pipelines.PricePipeline': 300,
'myproject.pipelines.JsonWriterPipeline': 800,
}
分配給每個類的整型值,確定了他們運行的順序,item按數字從低到高的順序,通過pipeline,通常將這些數字定義在0-1000範圍內。