官方文件spider引數中提到,可以使用scrapy crawl
命令的-a
選項向spider傳遞引數:
scrapy crawl myspider -a arg1=value1 -a arg2=value2
這些引數會被傳遞到自定義的myspider
類的建構函式,並且超類spider
的建構函式會將其拷貝到屬性中:
import scrapy
class
myspider
(scrapy.spider)
: name =
'myspider'
def__init__
(self,
*args,
**kwargs)
:# kwargs['arg1'] == 'value1'
# kwargs['arg2'] == 'value2'
super()
.__init__(
*args,
**kwargs)
# self.arg1 == 'value1'
# self.arg2 == 'value2'
那麼這些命令列引數是如何被解析,並最終設定為spider的屬性的?下面通過原始碼分析這一過程。
從scrapy的命令列模組scrapy.cmdline
入手,通過命令列輸入的命令由該模組中的execute()
函式執行:
這裡有兩個關鍵的物件:parser
是python內建模組optparse
中的optionparser
類的物件,用於解析命令列引數;cmd
是命令類的物件(crawl
命令對應scrapy.commands.crawl.command
類)
該函式的幾個關鍵步驟:
例如,待解析的命令列引數為-a arg1=value1 -a arg2=value2
,解析結果為opts
,則opts.spargs
是長度為2的列表['arg1=value1', 'arg2=value2']
(2)處理解析結果
baserunspidercommand
的process_options()
方法解析了opts.spargs
並將其轉換為字典
因此['arg1=value1', 'arg2=value2']
將變為
至此,解析命令列引數已完成,下面分析cmd.run()
如何使用這些解析結果。
檢視scrapy.commands.crawl.command
的run()
方法的**:
引數opts
為之前的解析結果,run()
方法以關鍵字引數的形式將opts.spargs
傳入scrapy.crawler.crawlerprocess
類的crawl()
方法,該方法繼承自crawlerrunner.crawl()
,繼續跟蹤該方法的呼叫過程
經過crawlerrunner.crawl()->crawlerrunner._crawl()->crawler.crawl()->crawler()._create_spider()
幾次呼叫後,kwargs
(即之前的opts.spargs
)最終被傳遞到spider.from_crawler()
方法,上圖中最後一行的spidercls
就是自定義的myspider
類
檢視spider.from_crawler()
方法的**:
可以看到,kwargs
被傳入cls
(即自定義的myspider類
)的建構函式,如果myspider
類沒有定義建構函式則繼承spider
類的建構函式
檢視spider
類的**,發現其建構函式中的下面這行**將kwargs
中的鍵值對轉換為自身的屬性:
至此spider引數的傳遞過程已經分析清楚。
Scrapy原始碼閱讀 response處理過程
以官方教程quotesspider為例,結合原始碼分析一下scrapy中response的處理過程。下面是待爬取的網頁,紅框中的是目標html標籤 quote文字內容 如果output是request物件,則將其交給引擎準備繼續爬取,開啟executionengine類的crawl方法可以看到引擎直...
《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具
檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...
原始碼閱讀 Glide原始碼閱讀之with方法(一)
前言 本篇基於4.8.0版本 原始碼閱讀 glide原始碼閱讀之with方法 一 原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 大多數情況下,我們使用glide 就一句 但是這一句 裡面蘊含著成噸的 with方法有以下幾個過載方法 publi...