用Scrapy已經有一段時間了,覺得該是看一下源碼的時候了。最開始用的時候還是0.16的版本,現在穩定版已經到了0.18。結合使用Scrapy的過程,先從Scrapy的命令行看起。
一、准備
下載源代碼,scrapy托管在github上,可以直接去項目主頁(https://github.com/scrapy/scrapy)通過各種方式(ssh、svn、git、下載壓縮包等)下載源碼。
IDE我用的是pyCharm,這個工具很強大,但並不是免費的(有免費的社區版),方便看代碼和debug。
scrapy版本:0.18.2,為了方便,這里用scrapy_home帶至scrapy源碼所在目錄路徑。
二、從cmdline.py說起
scrapy通過自帶的命令行方式可以實現快速構建、執行等。而這一切的功能都是從cmdline.py這個模塊開始的。當我們敲下scrapy <command> [options] [args]的命令時,都是通過該模塊來解析,然后執行具體的任務的。這個可以從scrapy_home/bin/scrapy這個文件下看到,這個文件的內容也很短,就幾行而已:
顯然,調用的是cmdline.py這個模塊的execute()函數。接下來就簡單看一夏cmdline.py這個模塊的具體代碼。
三、cmdline.py的實現
scrapy命令的執行方式如下:
scrapy <command> [options] [args]
通過代碼可以看到cmdline.py中execute()主要做了一下幾個工作:
- 處理參數信息為空的情況;
- 處理配置信息(包含向后兼容的代碼),這樣新的scrapy可以處理以前老版本下生成的項目;
- 判斷目前執行scrapy命令的當前目錄是否包含一個scrapy project,因為在scrapy project中可以執行更多的command選擇;
- 判斷傳入的command是否正確,不正確的話給出提示信息;
- 如果命令正確,則根據傳入的options和args用一個parser來解析成command可以用的方式,記錄在cmd中;
- _run_print_help()函數調用cmd.process_options()來執行cmd的選項設置;
process_options()函數在command.py的ScrapyCommand類中定義,該類是其他所有scrapy command(如crawl命令)的父類。 - 有了5,6處理得到的信息,然后加上setting信息,創建抓取器;
- _run_print_help()調用_run_command()函數來執行cmd;
這里要看的是_run_command()這個函數,由此函數開始,不同的命令調用不同的run函數執行。
四、總結
scrapy的執行從scrapy_home/bin/scrapy這個腳本開始,調用cmdline這個模塊。cmdline模塊完成命令的解析,配置的讀取和設置等等一系列工作,更具不同的命令將調用對應的模塊來繼續完成該命令的工作。每個具體的命令對應於一個scrapy_home/scrapy/commands包下具體的模塊的一個模塊。而這些命令都是ScrapyCommand這個類的子類,均override了run()這個函數,各命令的run()來完成自己不同的工作。