擴展框架提供一個機制,使得你能將自定義功能綁定到 Scrapy。
擴展只是正常的類,它們在 Scrapy 啟動時被實例化、初始化。
擴展使用 Scrapy settings 管理它們的設(shè)置,這跟其他 Scrapy 代碼一樣。
通常擴展需要給它們的設(shè)置加上前綴,以避免跟已有(或?qū)?的擴展沖突。 比如,一個擴展處理 Google Sitemaps,則可以使用類似 GOOGLESITEMAP_ENABLED、GOOGLESITEMAP_DEPTH 等設(shè)置。
擴展在擴展類被實例化時加載和激活。 因此,所有擴展的實例化代碼必須在類的構(gòu)造函數(shù)(__init__)中執(zhí)行。
要使得擴展可用,需要把它添加到 Scrapy 的 EXTENSIONS 配置中。在 EXTENSIONS 中,每個擴展都使用一個字符串表示,即擴展類的全 Python 路徑。比如:
EXTENSIONS = {
'scrapy.contrib.corestats.CoreStats': 500,
'scrapy.telnet.TelnetConsole': 500,
}
如你所見,EXTENSIONS 配置是一個 dict,key 是擴展類的路徑,value 是順序,它定義擴展加載的順序。擴展順序不像中間件的順序那么重要,而且擴展之間一般沒有關(guān)聯(lián)。擴展加載的順序并不重要,因為它們并不相互依賴。
如果你需要添加擴展而且它依賴別的擴展,你就可以使用該特性了。
這也是為什么 Scrapy 的配置項 EXTENSIONS_BASE(它包括了所有內(nèi)置且開啟的擴展)定義所有擴展的順序都相同(500)。
并不是所有可用的擴展都會被開啟。一些擴展經(jīng)常依賴一些特別的配置。 比如,HTTP Cache 擴展是可用的但默認是禁用的,除非 HTTPCACHE_ENABLED 配置項設(shè)置了。
為了禁用一個默認開啟的擴展(比如,包含在 EXTENSIONS_BASE 中的擴展),需要將其順序(order)設(shè)置為 None。比如:
EXTENSIONS = {
'scrapy.contrib.corestats.CoreStats': None,
}
實現(xiàn)你的擴展很簡單。每個擴展是一個單一的 Python class,它不需要實現(xiàn)任何特殊的方法。
Scrapy 擴展(包括 middlewares 和 pipelines)的主要入口是 from_crawler 類方法,它接收一個 Crawler 類的實例,該實例是控制 Scrapy crawler 的主要對象。如果擴展需要,你可以通過這個對象訪問 settings,signals,stats,控制爬蟲的行為。
通常來說,擴展關(guān)聯(lián)到 signals 并執(zhí)行它們觸發(fā)的任務(wù)。
最后,如果 from_crawler 方法拋出 NotConfigured 異常,擴展會被禁用。否則,擴展會被開啟。
這里我們將實現(xiàn)一個簡單的擴展來演示上面描述到的概念。 該擴展會在以下事件時記錄一條日志:
該擴展通過 MYEXT_ENABLED 配置項開啟,items 的數(shù)量通過 MYEXT_ITEMCOUNT 配置項設(shè)置。
以下是擴展的代碼:
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)
記錄基本的統(tǒng)計信息,比如爬取的頁面和條目(items)。
如果統(tǒng)計收集器(stats collection)啟用了,該擴展開啟核心統(tǒng)計收集(參考數(shù)據(jù)收集(Stats Collection))。
提供一個 telnet 控制臺,用于進入當前執(zhí)行的 Scrapy 進程的 Python 解析器,這對代碼調(diào)試非常有幫助。
telnet 控制臺通過 TELNETCONSOLE_ENABLED 配置項開啟,服務(wù)器會監(jiān)聽 TELNETCONSOLE_PORT 指定的端口。
注解
This extension does not work in Windows.
監(jiān)控 Scrapy 進程內(nèi)存使用量,并且:
當內(nèi)存用量達到 MEMUSAGE_WARNING_MB 指定的值,發(fā)送提醒郵件。當內(nèi)存用量達到 MEMUSAGE_LIMIT_MB 指定的值,發(fā)送提醒郵件,同時關(guān)閉 spider,Scrapy 進程退出。
該擴展通過 MEMUSAGE_ENABLED 配置項開啟,可以使用以下選項:
該擴展用于調(diào)試內(nèi)存使用量,它收集以下信息:
開啟該擴展,需打開 MEMDEBUG_ENABLED 配置項。 信息將會存儲在統(tǒng)計信息(stats)中。
當某些狀況發(fā)生,spider 會自動關(guān)閉。每種情況使用指定的關(guān)閉原因。
關(guān)閉 spider 的情況可以通過下面的設(shè)置項配置:
默認值: 0
一個整數(shù)值,單位為秒。如果一個 spider 在指定的秒數(shù)后仍在運行, 它將以 closespider_timeout 的原因被自動關(guān)閉。如果值設(shè)置為 0(或者沒有設(shè)置),spiders 不會因為超時而關(guān)閉。
缺省值: 0
一個整數(shù)值,指定條目的個數(shù)。如果 spider 爬取條目數(shù)超過了指定的數(shù),并且這些條目通過 item pipeline 傳遞,spider 將會以 closespider_itemcount 的原因被自動關(guān)閉。
新版功能。
缺省值: 0
一個整數(shù)值,指定最大的抓取響應(yīng)(reponses)數(shù)。 如果 spider 抓取數(shù)超過指定的值,則會以 closespider_pagecount 的原因自動關(guān)閉。 如果設(shè)置為 0(或者未設(shè)置),spiders 不會因為抓取的響應(yīng)數(shù)而關(guān)閉。
新版功能。
缺省值: 0
一個整數(shù)值,指定 spider 可以接受的最大錯誤數(shù)。 如果 spider 生成多于該數(shù)目的錯誤,它將以 closespider_errorcount 的原因關(guān)閉。 如果設(shè)置為 0(或者未設(shè)置),spiders 不會因為發(fā)生錯誤過多而關(guān)閉。
這個簡單的擴展可用來在一個域名爬取完畢時發(fā)送提醒郵件, 包含 Scrapy 收集的統(tǒng)計信息。 郵件會發(fā)送個通過 STATSMAILER_RCPTS 指定的所有接收人。
當收到 SIGQUIT 或 SIGUSR2 信號,spider 進程的信息將會被存儲下來。存儲的信息包括:
scrapy.utils.engin.get_engine_status())當堆棧信息和 engine 狀態(tài)存儲后,Scrapy 進程繼續(xù)正常運行。
該擴展只在 POSIX 兼容的平臺上可運行(比如不能在 Windows 運行), 因為 SIGQUIT 和 SIGUSR2 信號在 Windows 上不可用。
至少有兩種方式可以向 Scrapy 發(fā)送 SIGQUIT 信號:
在 Scrapy 進程運行時通過按 Ctrl-(僅 Linux 可行?)
運行該命令(<pid>是 Scrapy 運行的進程):
kill -QUIT <pid>
當收到 SIGUSR2 信號,將會在 Scrapy 進程中調(diào)用 Python debugger。debugger 退出后,Scrapy 進程繼續(xù)正常運行。
更多信息參考 Debugging in Python。
該擴展只在 POSIX 兼容平臺上工作(比如不能再 Windows 上運行)。