鍍金池/ 教程/ Python/ Item Pipeline
Benchmarking
命令行工具(Command line tools)
下載器中間件(Downloader Middleware)
信號(hào)(Signals)
Telnet 終端(Telnet Console)
初窺 Scrapy
數(shù)據(jù)收集(Stats Collection)
Scrapyd
通用爬蟲(Broad Crawls)
Item Loaders
試驗(yàn)階段特性
Scrapy 入門教程
自動(dòng)限速(AutoThrottle)擴(kuò)展
Settings
Scrapy 終端(Scrapy shell)
下載項(xiàng)目圖片
DjangoItem
調(diào)試(Debugging)Spiders
選擇器(Selectors)
Feed exports
Spiders Contracts
借助 Firefox 來爬取
Logging
Spiders
Ubuntu 軟件包
實(shí)踐經(jīng)驗(yàn)(Common Practices)
安裝指南
Item Exporters
擴(kuò)展(Extensions)
Items
Spider 中間件(Middleware)
異常(Exceptions)
例子
發(fā)送 email
架構(gòu)概覽
常見問題(FAQ)
Jobs:暫停,恢復(fù)爬蟲
核心 API
使用 Firebug 進(jìn)行爬取
Item Pipeline
Link Extractors
Web Service
調(diào)試內(nèi)存溢出

Item Pipeline

當(dāng) Item 在 Spider 中被收集之后,它將會(huì)被傳遞到 Item Pipeline,一些組件會(huì)按照一定的順序執(zhí)行對(duì) Item 的處理。

每個(gè) item pipeline 組件(有時(shí)稱之為“Item Pipeline”)是實(shí)現(xiàn)了簡(jiǎn)單方法的 Python 類。他們接收到 Item 并通過它執(zhí)行一些行為,同時(shí)也決定此 Item 是否繼續(xù)通過 pipeline,或是被丟棄而不再進(jìn)行處理。

以下是 item pipeline 的一些典型應(yīng)用:

  • 清理 HTML 數(shù)據(jù)
  • 驗(yàn)證爬取的數(shù)據(jù)(檢查 item 包含某些字段)
  • 查重(并丟棄)
  • 將爬取結(jié)果保存到數(shù)據(jù)庫中

編寫你自己的 item pipeline

編寫你自己的 item pipeline 很簡(jiǎn)單,每個(gè) item pipeline 組件是一個(gè)獨(dú)立的 Python 類,同時(shí)必須實(shí)現(xiàn)以下方法:

process_item(self, item, spider)

每個(gè) item pipeline 組件都需要調(diào)用該方法,這個(gè)方法必須返回一個(gè) Item (或任何繼承類)對(duì)象, 或是拋出 DropItem 異常,被丟棄的 item 將不會(huì)被之后的 pipeline 組件所處理。

參數(shù):

  • item (Item 對(duì)象) – 被爬取的 item
  • spider (Spider 對(duì)象) – 爬取該 item 的 spider

此外,他們也可以實(shí)現(xiàn)以下方法:

open_spider(self, spider)

當(dāng) spider 被開啟時(shí),這個(gè)方法被調(diào)用。

參數(shù):

  • spider (Spider 對(duì)象) – 被開啟的 spider

close_spider(spider)

當(dāng) spider 被關(guān)閉時(shí),這個(gè)方法被調(diào)用

參數(shù):

spider (Spider 對(duì)象) – 被關(guān)閉的 spider

from_crawler(cls, crawler)

If present, this classmethod is called to create a pipeline instance from a Crawler. It must return a new instance of the pipeline. Crawler object provides access to all Scrapy core components like settings and signals; it is a way for pipeline to access them and hook its functionality into Scrapy.

參數(shù):

crawler (Crawler object) – crawler that uses this pipeline

Item pipeline 樣例

驗(yàn)證價(jià)格,同時(shí)丟棄沒有價(jià)格的 item

讓我們來看一下以下這個(gè)假設(shè)的 pipeline,它為那些不含稅(price_excludes_vat 屬性)的 item 調(diào)整了 price 屬性,同時(shí)丟棄了那些沒有價(jià)格的 item:

from scrapy.exceptions import DropItem

class PricePipeline(object):

    vat_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,存儲(chǔ)到一個(gè)獨(dú)立地 items.jl 文件,每行包含一個(gè)序列化為 JSON 格式的 item:

import json

class JsonWriterPipeline(object):

    def __init__(self):
        self.file = open('items.jl', 'wb')

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item

注解

JsonWriterPipeline 的目的只是為了介紹怎樣編寫 item pipeline,如果你想要將所有爬取的 item 都保存到同一個(gè) JSON 文件, 你需要使用 Feed exports 。

Write items to MongoDB

In this example we’ll write items to MongoDB using pymongo. MongoDB address and database name are specified in Scrapy settings; MongoDB collection is named after item class.

The main point of this example is to show how to use from_crawler() method and how to clean up the resources properly.

注解

Previous example (JsonWriterPipeline) doesn’t clean up resources properly. Fixing it is left as an exercise for the reader. import pymongo

class MongoPipeline(object):

    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.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        collection_name = item.__class__.__name__
        self.db[collection_name].insert(dict(item))
        return item

去重

一個(gè)用于去重的過濾器,丟棄那些已經(jīng)被處理過的 item。讓我們假設(shè)我們的 item 有一個(gè)唯一的 id,但是我們 spider 返回的多個(gè) 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

啟用一個(gè) Item Pipeline 組件

為了啟用一個(gè) Item Pipeline 組件,你必須將它的類添加到 ITEM_PIPELINES 配置,就像下面這個(gè)例子:

ITEM_PIPELINES = {
    'myproject.pipelines.PricePipeline': 300,
    'myproject.pipelines.JsonWriterPipeline': 800,
}

分配給每個(gè)類的整型值,確定了他們運(yùn)行的順序,item 按數(shù)字從低到高的順序,通過 pipeline,通常將這些數(shù)字定義在 0-1000 范圍內(nèi)。

上一篇:Ubuntu 軟件包下一篇:Spiders Contracts