爬蟲(2):Pipeline

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範圍內。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章