Item Pipeline
當Item在Spider中被收集後,它會被傳到Item Pipline,一些組件會按照一定的順序執行對Item的處理。
每個item pipeline組件是實現了簡單方法的Python類。他們接受到Item並通過它執行一些行爲,同時也決定此item是否繼續通過pipeline,或是被丟棄而不再進行處理。
以下是item pipline的一些典型應用:
-
清理HTML數據
-
驗證爬取的數據(檢查item包含某些字段)
-
查重(並丟棄)
-
將爬取結果保存到數據庫中
編寫你自己的item pipeline
每個item pipline組件是一個獨立的Python類,同時必須實現以下方法:
process_item(self,item,spider)
每個item pipline組件都需要調用該方法。這個方法必須返回一個具有數據的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的新對象,Crawler提供了所有面向Scrapy核心組件(比如settings,signals)的連接,這是pipeline連接他們並勾連他們的功能
到Scrapy的重要途徑.
參數:cralwer(clawler對象)-使用這個pipeline的cralwer。
Item pipeline樣例
驗證價格,同時丟棄沒有價格的item
功能:爲那些不含稅(price_excludes_vat屬性)的item調整了price屬性,同時丟棄了那些沒有價格的item:
from scrapy.exception import DropItem
class PricePipeline(object):
var_factor=1.15
def process_item(self,item,spider):
if item['price']:
if item['price_excludes_vat']:
item['price']=item['price']*self.vat_factor
return item
else:
raise DropItem("Missing price in %s" %item )
將item寫入JSON
以下pipeline將所有(從所有spider中)爬取到的item,存儲到一個序列化爲JSON格式的item:
import json
class JsonWriterPipeline(object):
def__init__(self):
self.file=open('items.jl','wb')
def process_item(self,item,spider):
line=json.dump(dict(item))+"\n"
self.file.writer(line)
return item
將items寫入MongoDB
在這個例子中我們將使用pymongo來向pymongo
裏寫items,MongoDB的地址和數據庫名字都在Scrapy settings裏;MongoDB集合在itemclass
後命名。這個例子的主要的點在於展現如何使用from_crawler()方法以及如何正確的清理資源。
import pymongo
class MongoPipeline(object):
collection_name='scrapy_items'
def __ init__(self,mongo_uri,mongo_db):
self.mongo_uri=mongo_uri
self.mongo_db=mongo_db
@classmethod
def from_crawler(cls,crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE','items'
)
def open_spider(self,spider):
self.client=pymongo.MongoClient(self.mongo_uri)
self.db=self.client[self.mogo_db]
def close_spider(self,spider):
self.client.close()
def process_item(self,item,spider):
self.db[self.collection_name].insert(dict(item))
return item
去重
一個用於去重的過濾器,丟棄那些已經被處理過的item。讓我們假設我們的item有一個唯一的id,但是我們的spider返回的多個item中包含有相同的id:
from scrapy.exception import DropItem
class DuplicatePipeline(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
啓用一個Item Pipeline組件
爲了啓用一個Item Pipeline組件,你必須把它的類添加到ITEM_PIPELINES配置。
ITEM_PIPELINES={
'myproject.pipelines.PricePipeline':300,
'myproject.pipeline.JsonWriterPipeline':800,
}
分配給每個類的整型值,確定了他們運行的順序,item按數字從低到高的順序,通過pipeline,通常將這些數字定義在0-1000範圍內。