Scrapy 運行架構與數據處理流程簡介
今天我們來重點看看 Scrapy 爬蟲框架的架構設計,它非常非常重要。Scrapy 的架構圖能幫助我們理解其背后的整個運行流程,是我們深度掌握和定制化開發 Scrapy 插件的一個重要基礎。此外,我們還會從整體角度過一遍 Scrapy 框架的源碼,后續部分章節會進入到 Scrapy 的源碼中去講解,因此有必要先熟悉一遍 Scrapy 的源碼目錄。
1. Scrapy 架構介紹
首先來看 Scrapy 最經典的架構設計圖,如下:
我們可以看到,Scrapy 框架中幾個比較核心的組件包括:
- 位于核心位置的稱為 Scrapy 引擎。它就好比一軍的總司令,負責把控全局,指揮其它組件,協同作戰;
- 圖上方的是調度器 Scheduler:它接收引擎發生過來的請求,按照先后順序,壓入隊列,同時會過濾重復請求;
- 圖下方的爬蟲 (Spiders) 組件,它主要負責構造 Request 請求發送給引擎,然后引擎會將該 Request 請求結果交到該組件中進行處理,解析出想要的 items 結果并傳給 Item Pipelines 進行后續的處理;
- 圖右邊的**下載器 (Downloader) **,很明顯它的職責是從互聯網上下載網頁數據;
- 最左邊的 Item Pipeline,用于對生成的 Item 數據進行進一步處理。比如數據清洗、保存到數據庫等;
- **中間件 (Downloaders Middlewares) **,包括爬蟲中間件、下載中間件等,它們都是用于中間處理數據的。我們可以在此處選擇對 item 的數據進行清洗、去重等操作,也可以在這里選擇使用何種方式 (MySQL、MongoDB、Redis、甚至文件等) 保存得到的 item;
2. Scrapy 數據處理流程
而下面這張圖是非常經典的 Scrapy 框架的數據處理流程圖,這張數據流圖非常重要,它詳細描述了 Scrapy 框架背后的運行流程。按照圖中的序號,我來給大家描述下 Scrapy 框架中的數據處理流程:
-
Spider 構造 Request 請求并提交給 Scrapy 引擎;這步中存在中間件操作,可以對請求設置代理 IP 等后再發送給引擎;
-
引擎將請求發生給調度器,調度器會根據請求中設置的優先級確定要執行的請求順序;
-
引擎從調度器中獲取將要執行的請求;
-
引擎通過下載中間件后,將請求傳給下載器執行網頁下載;
-
得到 HTTP 響應結果并將其封裝成 Response 類,然后經過下載中間件處理后傳遞回引擎;
-
引擎接收到請求的響應結果后,通過爬蟲的中間件將其發送給爬蟲 (Spider) 去處理,對應我們前面案例中的
parse()
方法或者自定義的回調方法book_list_parse()
; -
爬蟲會將網頁數據抽取成一條數據實體 (Item) 以及新的請求(比如下一頁的 URL),再次發送給引擎處理;
-
引擎將爬蟲獲取到的 Item 發送給項目管道 (Item Pipelines),在項目管道中我們可以實現數據的持久化,比如保存到 MySQL 數據庫或者 MongoDB 中 。同時,如果有新的請求也會發送給引擎,在繼續從第二步開始重復執行,直到最后調度器中沒有請求為止。
大家將這八個步驟和我們前面實現的互動出版網數據爬取的代碼進行實例分析,是不是會有更進一步的理解呢?這上面的架構圖和數據流圖對于我們學習和理解 Scrapy 框架都非常重要,大家一定要掌握!
3. Scrapy 源碼初探
看過了 Scrapy 的架構和數據處理流程,我們來簡單了解下 Scrapy 框架的源碼結構。熟悉和理解 Scrapy 框架的源碼,對于我們日常開發的好處不言而喻,我總結了如下三點原因:
- 熟悉掌握 Scrapy 框架用法的最好方式就是閱讀源碼;
- 提升編程能力的最好途徑也是閱讀源碼;此外,Twisted 模塊在 Scrapy 框架中應用廣泛,而國內關于該框架資源十分匱乏,我們可以借助 Scrapy 框架來完整學習 Twisted 模塊的使用,體驗這樣一個異步通信機制帶給我們的性能體驗;
- 方便問題排錯以及后續基于 Scrapy 的深度定制開發。只有熟悉了 Scrapy 源碼,我們才能針對 Scrapy 框架進行深度定制開發,實現與我們業務相關的爬蟲框架;另外,熟悉源碼能方便我們在調試 Scrapy 爬蟲時快速定位為題原因,高效解決問題,這是一個經驗豐富的爬蟲工程師必須具備的技能;
截止到這篇文章撰寫完成(2020 年 7 月 12 日),Scrapy 最新發布的版本是 2.2.0 版本。我們從 github 上選擇穩定的 scrapy 源碼包,下載下來后解壓并使用 VScode 軟件打開該源碼目錄。下面就是 Scrapy-2.2.0 的源碼內容:
我們依次對這些源碼目錄和文件進行簡單說明,后面我們在學習中會逐漸深入源碼去分析 Scrapy 框架的行為以及追蹤爬蟲的執行過程。來依次看看 Scrapy 源碼的目錄結構:
- commands目錄:該目錄下的文件正是 scrapy 所支持的命令。比如我們生成爬蟲項目使用的命令
scrapy startproject xxxx
對應著文件startproject.py
,命令scrapy shell http://www.baidu.com
對應的執行文件為shell.py
。因此,如果我們要追蹤 scrapy 命令的運行過程就可以從這里入手跟蹤代碼了; - contracts 目錄:定義了若干簡單 python 文件;
- core 目錄:非常核心,定義了 scrapy 框架中的核心類與方法;
- downloadermiddleswares 目錄:下載中間件相關的代碼;
- extensions 目錄:定義了一些擴展方法,比如 debug.py,telnet.py 等代碼文件;
- http 目錄:該目錄下定義了 Request 和 Response 類及其相關的擴展類。下節和下下節會詳細介紹該目錄下的源碼文件;
- linkextractors 目錄:這里的代碼主要是輔助
scrapy
核心對網頁的鏈接進行抽取,定義了一系列的抽取類; - loader目錄:該目錄下的代碼是 Item Loader,具體信息可以參考源碼下的
docs/topics/loaders.rst
文件進行深入了解; - pipelines 目錄:和 pipelines 模塊相關,主要對爬蟲抽取到的 items 數據進行再次處理;
- selector 目錄:該目錄下定義了解析網頁的 Selector,主要是封裝了 parsel 模塊的 Selector 和 SelectorList;
- settings 目錄:這里定義了操作配置文件的相關類以及一個默認的配置文件 (default_settings.py);
- spidermiddlewares 目錄:定義了爬蟲中間件的相關類與方法,
- spiders 目錄:定義了爬蟲模塊的核心類;
- templates 目錄:下面保存了創建 scrapy 項目所需要的一些模板文件;
- utils 目錄:一些常用的輔助函數;
- 其他文件:一些比較核心的代碼文件都在這里,比如 cmdline.py、crawler.py、shell.py 等。
看完這些介紹后有沒有什么感覺?是不是覺得一個非常流行的 Python 框架也就那樣?
當然不是,在這里我們只是介紹了它的表面,并沒有深究其內部細節。任何一個流行的框架必有其獨特的優勢,且必須代碼精良。
Scrapy 框架在簡潔易用上做的非常不錯,此外由于其使用 Twisted 作為其異步處理框架,因此基于 Scrapy 框架開發的爬蟲一般具有不錯的性能,加之良好的社區、文檔和框架生態,終造就了今天的 Scrapy。接下來,我們會慢慢深入這些目錄去探索 Scrapy 的源碼,最后實現徹底掌握 Scrapy 框架的目的。
4. 小結
今天我們詳細描述了 Scrapy 框架的架構設計,介紹了其重點的組成模塊和工作職責,接下來我們對 Scrapy 框架的源碼進行了簡單的介紹和預覽,為我們后續深入分析 Scrapy 框架打好相應的基礎。