鍍金池/ 教程/ Python/ 擴(kuò)展(Extensions)
Benchmarking
命令行工具(Command line tools)
下載器中間件(Downloader Middleware)
信號(hào)(Signals)
Telnet 終端(Telnet Console)
初窺 Scrapy
數(shù)據(jù)收集(Stats Collection)
Scrapyd
通用爬蟲(chóng)(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)概覽
常見(jiàn)問(wèn)題(FAQ)
Jobs:暫停,恢復(fù)爬蟲(chóng)
核心 API
使用 Firebug 進(jìn)行爬取
Item Pipeline
Link Extractors
Web Service
調(diào)試內(nèi)存溢出

擴(kuò)展(Extensions)

擴(kuò)展框架提供一個(gè)機(jī)制,使得你能將自定義功能綁定到 Scrapy。

擴(kuò)展只是正常的類,它們?cè)?Scrapy 啟動(dòng)時(shí)被實(shí)例化、初始化。

擴(kuò)展設(shè)置(Extension settings)

擴(kuò)展使用 Scrapy settings 管理它們的設(shè)置,這跟其他 Scrapy 代碼一樣。

通常擴(kuò)展需要給它們的設(shè)置加上前綴,以避免跟已有(或?qū)?lái))的擴(kuò)展沖突。 比如,一個(gè)擴(kuò)展處理 Google Sitemaps,則可以使用類似 GOOGLESITEMAP_ENABLED、GOOGLESITEMAP_DEPTH 等設(shè)置。

加載和激活擴(kuò)展

擴(kuò)展在擴(kuò)展類被實(shí)例化時(shí)加載和激活。 因此,所有擴(kuò)展的實(shí)例化代碼必須在類的構(gòu)造函數(shù)(__init__)中執(zhí)行。

要使得擴(kuò)展可用,需要把它添加到 Scrapy 的 EXTENSIONS 配置中。在 EXTENSIONS 中,每個(gè)擴(kuò)展都使用一個(gè)字符串表示,即擴(kuò)展類的全 Python 路徑。比如:

EXTENSIONS = {
    'scrapy.contrib.corestats.CoreStats': 500,
    'scrapy.telnet.TelnetConsole': 500,
}

如你所見(jiàn),EXTENSIONS 配置是一個(gè) dict,key 是擴(kuò)展類的路徑,value 是順序,它定義擴(kuò)展加載的順序。擴(kuò)展順序不像中間件的順序那么重要,而且擴(kuò)展之間一般沒(méi)有關(guān)聯(lián)。擴(kuò)展加載的順序并不重要,因?yàn)樗鼈儾⒉幌嗷ヒ蕾嚒?/p>

如果你需要添加擴(kuò)展而且它依賴別的擴(kuò)展,你就可以使用該特性了。

這也是為什么 Scrapy 的配置項(xiàng) EXTENSIONS_BASE(它包括了所有內(nèi)置且開(kāi)啟的擴(kuò)展)定義所有擴(kuò)展的順序都相同(500)。

可用的(Available)、開(kāi)啟的(enabled)和禁用的(disabled)的擴(kuò)展

并不是所有可用的擴(kuò)展都會(huì)被開(kāi)啟。一些擴(kuò)展經(jīng)常依賴一些特別的配置。 比如,HTTP Cache 擴(kuò)展是可用的但默認(rèn)是禁用的,除非 HTTPCACHE_ENABLED 配置項(xiàng)設(shè)置了。

禁用擴(kuò)展(Disabling an extension)

為了禁用一個(gè)默認(rèn)開(kāi)啟的擴(kuò)展(比如,包含在 EXTENSIONS_BASE 中的擴(kuò)展),需要將其順序(order)設(shè)置為 None。比如:

EXTENSIONS = {
    'scrapy.contrib.corestats.CoreStats': None,
}

實(shí)現(xiàn)你的擴(kuò)展

實(shí)現(xiàn)你的擴(kuò)展很簡(jiǎn)單。每個(gè)擴(kuò)展是一個(gè)單一的 Python class,它不需要實(shí)現(xiàn)任何特殊的方法。

Scrapy 擴(kuò)展(包括 middlewares 和 pipelines)的主要入口是 from_crawler 類方法,它接收一個(gè) Crawler 類的實(shí)例,該實(shí)例是控制 Scrapy crawler 的主要對(duì)象。如果擴(kuò)展需要,你可以通過(guò)這個(gè)對(duì)象訪問(wèn) settings,signals,stats,控制爬蟲(chóng)的行為。

通常來(lái)說(shuō),擴(kuò)展關(guān)聯(lián)到 signals 并執(zhí)行它們觸發(fā)的任務(wù)。

最后,如果 from_crawler 方法拋出 NotConfigured 異常,擴(kuò)展會(huì)被禁用。否則,擴(kuò)展會(huì)被開(kāi)啟。

擴(kuò)展例子(Sample extension)

這里我們將實(shí)現(xiàn)一個(gè)簡(jiǎn)單的擴(kuò)展來(lái)演示上面描述到的概念。 該擴(kuò)展會(huì)在以下事件時(shí)記錄一條日志:

  • spider 被打開(kāi)
  • spider 被關(guān)閉
  • 爬取了特定數(shù)量的條目(items)

該擴(kuò)展通過(guò) MYEXT_ENABLED 配置項(xiàng)開(kāi)啟,items 的數(shù)量通過(guò) MYEXT_ITEMCOUNT 配置項(xiàng)設(shè)置。

以下是擴(kuò)展的代碼:

from scrapy import signals
from scrapy.exceptions import NotConfigured

class SpiderOpenCloseLogging(object):

    def __init__(self, item_count):
        self.item_count = item_count

        self.items_scraped = 0

    @classmethod
    def from_crawler(cls, crawler):
        # first check if the extension should be enabled and raise

        # NotConfigured otherwise

        if not crawler.settings.getbool('MYEXT_ENABLED'):

            raise NotConfigured

        # get the number of items from settings

        item_count = crawler.settings.getint('MYEXT_ITEMCOUNT', 1000)

        # instantiate the extension object

        ext = cls(item_count)

        # connect the extension object to signals

        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)

        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)

        crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped)

        # return the extension object

        return ext

    def spider_opened(self, spider):
        spider.log("opened spider %s" % spider.name)

    def spider_closed(self, spider):
        spider.log("closed spider %s" % spider.name)

    def item_scraped(self, item, spider):
        self.items_scraped += 1

        if self.items_scraped % self.item_count == 0:
            spider.log("scraped %d items" % self.items_scraped)

內(nèi)置擴(kuò)展介紹

通用擴(kuò)展

記錄統(tǒng)計(jì)擴(kuò)展(Log Stats extension)

class scrapy.contrib.logstats.LogStats

記錄基本的統(tǒng)計(jì)信息,比如爬取的頁(yè)面和條目(items)。

核心統(tǒng)計(jì)擴(kuò)展(Core Stats extension)

class scrapy.contrib.corestats.CoreStats

如果統(tǒng)計(jì)收集器(stats collection)啟用了,該擴(kuò)展開(kāi)啟核心統(tǒng)計(jì)收集(參考數(shù)據(jù)收集(Stats Collection))。

Telnet console 擴(kuò)展

class scrapy.telnet.TelnetConsole

提供一個(gè) telnet 控制臺(tái),用于進(jìn)入當(dāng)前執(zhí)行的 Scrapy 進(jìn)程的 Python 解析器,這對(duì)代碼調(diào)試非常有幫助。

telnet 控制臺(tái)通過(guò) TELNETCONSOLE_ENABLED 配置項(xiàng)開(kāi)啟,服務(wù)器會(huì)監(jiān)聽(tīng) TELNETCONSOLE_PORT 指定的端口。

內(nèi)存使用擴(kuò)展(Memory usage extension)

class scrapy.contrib.memusage.MemoryUsage

注解

This extension does not work in Windows.

監(jiān)控 Scrapy 進(jìn)程內(nèi)存使用量,并且:

  1. 如果使用內(nèi)存量超過(guò)某個(gè)指定值,發(fā)送提醒郵件
  2. 如果超過(guò)某個(gè)指定值,關(guān)閉 spider

當(dāng)內(nèi)存用量達(dá)到 MEMUSAGE_WARNING_MB 指定的值,發(fā)送提醒郵件。當(dāng)內(nèi)存用量達(dá)到 MEMUSAGE_LIMIT_MB 指定的值,發(fā)送提醒郵件,同時(shí)關(guān)閉 spider,Scrapy 進(jìn)程退出。

該擴(kuò)展通過(guò) MEMUSAGE_ENABLED 配置項(xiàng)開(kāi)啟,可以使用以下選項(xiàng):

  • MEMUSAGE_LIMIT_MB
  • MEMUSAGE_WARNING_MB
  • MEMUSAGE_NOTIFY_MAIL
  • MEMUSAGE_REPORT

內(nèi)存調(diào)試擴(kuò)展(Memory debugger extension)

class scrapy.contrib.memdebug.MemoryDebugger

該擴(kuò)展用于調(diào)試內(nèi)存使用量,它收集以下信息:

開(kāi)啟該擴(kuò)展,需打開(kāi) MEMDEBUG_ENABLED 配置項(xiàng)。 信息將會(huì)存儲(chǔ)在統(tǒng)計(jì)信息(stats)中。

關(guān)閉 spider 擴(kuò)展

class scrapy.contrib.closespider.CloseSpider

當(dāng)某些狀況發(fā)生,spider 會(huì)自動(dòng)關(guān)閉。每種情況使用指定的關(guān)閉原因。

關(guān)閉 spider 的情況可以通過(guò)下面的設(shè)置項(xiàng)配置:

  • CLOSESPIDER_TIMEOUT
  • CLOSESPIDER_ITEMCOUNT
  • CLOSESPIDER_PAGECOUNT
  • CLOSESPIDER_ERRORCOUNT

CLOSESPIDER_TIMEOUT

默認(rèn)值: 0

一個(gè)整數(shù)值,單位為秒。如果一個(gè) spider 在指定的秒數(shù)后仍在運(yùn)行, 它將以 closespider_timeout 的原因被自動(dòng)關(guān)閉。如果值設(shè)置為 0(或者沒(méi)有設(shè)置),spiders 不會(huì)因?yàn)槌瑫r(shí)而關(guān)閉。

CLOSESPIDER_ITEMCOUNT

缺省值: 0

一個(gè)整數(shù)值,指定條目的個(gè)數(shù)。如果 spider 爬取條目數(shù)超過(guò)了指定的數(shù),并且這些條目通過(guò) item pipeline 傳遞,spider 將會(huì)以 closespider_itemcount 的原因被自動(dòng)關(guān)閉。

CLOSESPIDER_PAGECOUNT

新版功能。

缺省值: 0

一個(gè)整數(shù)值,指定最大的抓取響應(yīng)(reponses)數(shù)。 如果 spider 抓取數(shù)超過(guò)指定的值,則會(huì)以 closespider_pagecount 的原因自動(dòng)關(guān)閉。 如果設(shè)置為 0(或者未設(shè)置),spiders 不會(huì)因?yàn)樽ト〉捻憫?yīng)數(shù)而關(guān)閉。

CLOSESPIDER_ERRORCOUNT

新版功能。

缺省值: 0

一個(gè)整數(shù)值,指定 spider 可以接受的最大錯(cuò)誤數(shù)。 如果 spider 生成多于該數(shù)目的錯(cuò)誤,它將以 closespider_errorcount 的原因關(guān)閉。 如果設(shè)置為 0(或者未設(shè)置),spiders 不會(huì)因?yàn)榘l(fā)生錯(cuò)誤過(guò)多而關(guān)閉。

StatsMailer extension

class scrapy.contrib.statsmailer.StatsMailer

這個(gè)簡(jiǎn)單的擴(kuò)展可用來(lái)在一個(gè)域名爬取完畢時(shí)發(fā)送提醒郵件, 包含 Scrapy 收集的統(tǒng)計(jì)信息。 郵件會(huì)發(fā)送個(gè)通過(guò) STATSMAILER_RCPTS 指定的所有接收人。

Debugging extensions

Stack trace dump extension

class scrapy.contrib.debug.StackTraceDump

當(dāng)收到 SIGQUITSIGUSR2 信號(hào),spider 進(jìn)程的信息將會(huì)被存儲(chǔ)下來(lái)。存儲(chǔ)的信息包括:

  1. engine 狀態(tài)(使用 scrapy.utils.engin.get_engine_status())
  2. 所有存活的引用(live references)(參考使用 trackref 調(diào)試內(nèi)存泄露)
  3. 所有線程的堆棧信息

當(dāng)堆棧信息和 engine 狀態(tài)存儲(chǔ)后,Scrapy 進(jìn)程繼續(xù)正常運(yùn)行。

該擴(kuò)展只在 POSIX 兼容的平臺(tái)上可運(yùn)行(比如不能在 Windows 運(yùn)行), 因?yàn)?SIGQUIT 和 SIGUSR2 信號(hào)在 Windows 上不可用。

至少有兩種方式可以向 Scrapy 發(fā)送 SIGQUIT 信號(hào):

在 Scrapy 進(jìn)程運(yùn)行時(shí)通過(guò)按 Ctrl-(僅 Linux 可行?) 運(yùn)行該命令(<pid>是 Scrapy 運(yùn)行的進(jìn)程):

kill -QUIT <pid>

調(diào)試擴(kuò)展(Debugger extension)

class scrapy.contrib.debug.Debugger

當(dāng)收到 SIGUSR2 信號(hào),將會(huì)在 Scrapy 進(jìn)程中調(diào)用 Python debugger。debugger 退出后,Scrapy 進(jìn)程繼續(xù)正常運(yùn)行。

更多信息參考 Debugging in Python。

該擴(kuò)展只在 POSIX 兼容平臺(tái)上工作(比如不能再 Windows 上運(yùn)行)。

上一篇:Logging下一篇:下載項(xiàng)目圖片