鍍金池/ 教程/ Python/ Spiders Contracts
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 來(lái)爬取
Logging
Spiders
Ubuntu 軟件包
實(shí)踐經(jīng)驗(yàn)(Common Practices)
安裝指南
Item Exporters
擴(kuò)展(Extensions)
Items
Spider 中間件(Middleware)
異常(Exceptions)
例子
發(fā)送 email
架構(gòu)概覽
常見問(wèn)題(FAQ)
Jobs:暫停,恢復(fù)爬蟲
核心 API
使用 Firebug 進(jìn)行爬取
Item Pipeline
Link Extractors
Web Service
調(diào)試內(nèi)存溢出

Spiders Contracts

新版功能。

注解

這是一個(gè)新引入(Scrapy 0.15)的特性,在后續(xù)的功能/API 更新中可能有所改變,查看 release notes 來(lái)了解更新。

測(cè)試 spider 是一件挺煩人的事情,尤其是只能編寫單元測(cè)試(unit test)沒有其他辦法時(shí),就更惱人了。 Scrapy 通過(guò)合同(contract)的方式來(lái)提供了測(cè)試 spider 的集成方法。

您可以硬編碼(hardcode)一個(gè)樣例(sample)url, 設(shè)置多個(gè)條件來(lái)測(cè)試回調(diào)函數(shù)處理 repsponse 的結(jié)果,來(lái)測(cè)試 spider 的回調(diào)函數(shù)。 每個(gè) contract 包含在文檔字符串(docstring)里,以@開頭。 查看下面的例子:

def parse(self, response):
    """ This function parses a sample response. Some contracts are mingled
    with this docstring.

    @url http://www.amazon.com/s?field-keywords=selfish+gene
    @returns items 1 16
    @returns requests 0 0
    @scrapes Title Author Year Price
    """

該回調(diào)函數(shù)使用了三個(gè)內(nèi)置的 contract 來(lái)測(cè)試:

class scrapy.contracts.default.UrlContract

該 constract(@url)設(shè)置了用于檢查 spider 的其他 constract 狀態(tài)的樣例 url。該 contract 是必須的,所有缺失該 contract 的回調(diào)函數(shù)在測(cè)試時(shí)將會(huì)被忽略:

@url url

class scrapy.contracts.default.ReturnsContract

該 contract(@returns)設(shè)置 spider 返回的 items 和 requests 的上界和下界。上界是可選的:

@returns item(s)|request(s) [min [max]]

class scrapy.contracts.default.ScrapesContract

該 contract(@scrapes)檢查回調(diào)函數(shù)返回的所有 item 是否有特定的 fields:

@scrapes field_1 field_2 ...

使用 check 命令來(lái)運(yùn)行 contract 檢查。

自定義 Contracts

如果您想要比內(nèi)置 scrapy contract 更為強(qiáng)大的功能,可以在您的項(xiàng)目里創(chuàng)建并設(shè)置您自己的 contract,并使用 SPIDER_CONTRACTS 設(shè)置來(lái)加載:

SPIDER_CONTRACTS = {
    'myproject.contracts.ResponseCheck': 10,
    'myproject.contracts.ItemValidate': 10,
}

每個(gè) contract 必須繼承 scrapy.contracts.Contract 并覆蓋下列三個(gè)方法:

class scrapy.contracts.Contract(method, *args)

參數(shù):

  • method (function) – contract 所關(guān)聯(lián)的回調(diào)函數(shù)
  • args (list) – 傳入 docstring 的(以空格區(qū)分的)argument 列表(list)
adjust_request_args(args)

接收一個(gè)字典(dict)作為參數(shù)。該參數(shù)包含了所有 Request 對(duì)象 參數(shù)的默認(rèn)值。該方法必須返回相同或修改過(guò)的字典。

pre_process(response)

該函數(shù)在 sample request 接收到 response 后,傳送給回調(diào)函數(shù)前被調(diào)用,運(yùn)行測(cè)試。

post_process(output)

該函數(shù)處理回調(diào)函數(shù)的輸出。迭代器(Iterators)在傳輸給該函數(shù)前會(huì)被列表化(listified)。

該樣例 contract 在 response 接收時(shí)檢查了是否有自定義 header。 在失敗時(shí) Raise scrapy.exceptions.ContractFaild 來(lái)展現(xiàn)錯(cuò)誤:

from scrapy.contracts import Contract
from scrapy.exceptions import ContractFail

class HasHeaderContract(Contract):
    """ Demo contract which checks the presence of a custom header
        @has_header X-CustomHeader
    """

    name = 'has_header'

    def pre_process(self, response):
        for header in self.args:
            if header not in response.headers:
                raise ContractFail('X-CustomHeader not present')