一、項目介紹
該項目是一個簡易分布式爬蟲系統,以分布式思想為基礎,通過多節點協作的方式,將大規模的網頁抓取任務分解,從而高效、快速地獲取網絡數據 。
項目地址:https://github.com/yanchengsi/distributed_crawler
三、項目實現
3.1 技術選型與相關開發文檔
一、場景分析
(一)要解決的問題
- 高效數據采集:需要從大量網頁中快速、準確地抓取目標數據,滿足數據需求方對數據及時性和完整性的要求。在面對海量網頁時,傳統單節點爬蟲效率低下,難以在規定時間內完成數據采集任務。
- 分布式任務管理:實現多節點協作,合理分配爬蟲任務,避免任務分配不均導致部分節點負載過高,而部分節點閑置的情況。同時,要確保任務的可靠分發與狀態跟蹤,保證每個任務都能得到妥善處理。
- 數據存儲與管理:對采集到的大量數據進行有效的存儲和管理,便于后續的數據處理、分析和查詢。需要保證數據的安全性和完整性,防止數據丟失或損壞。
- 系統穩定性與擴展性:系統應具備高穩定性,能夠長時間穩定運行,應對可能出現的網絡波動、節點故障等問題。同時,隨著業務規模的擴大,能夠方便地進行擴展,增加爬蟲節點或存儲資源。
(二)前提假設
- 數據規模假設:預計在項目運行初期,每天需要采集的數據量約為10GB,隨著業務的發展,數據量可能會以每月20%的速度增長。
- 硬件資源假設:假設每個爬蟲節點服務器的配置為8核CPU、16GB內存、1TB硬盤,網絡帶寬為100Mbps。存儲服務器配置為16核CPU、64GB內存、10TB硬盤,網絡帶寬為1Gbps。
- 網絡環境假設:項目運行在穩定的企業內部網絡環境中,網絡延遲較低且波動較小。但可能會受到外部網絡(如目標網站所在網絡)不穩定因素的影響。
- 數據類型假設:采集的數據主要為文本數據,包含少量圖片和視頻數據,數據結構相對較為規范。
(三)資源預估
- 存儲空間:根據數據規模假設,初期每天10GB的數據量,考慮到數據的存儲冗余和備份需求,預計初期需要500GB的存儲空間。隨著數據量的增長,每月需增加約100GB的存儲空間。
- 服務器數量:在項目初期,預計需要5臺爬蟲節點服務器和1臺存儲服務器。隨著業務發展,根據數據量增長和任務負載情況,適時增加爬蟲節點服務器和存儲服務器數量。
二、技術選型
(一)編程語言
選擇Python作為主要編程語言。Python具有豐富的第三方庫,如用于網絡請求的requests庫、用于數據處理的pandas庫、用于構建Web服務的Flask庫等,能夠大大提高開發效率。同時,Python語言簡潔易讀,便于團隊成員之間的協作開發和代碼維護。
(二)Web框架
采用Flask框架構建主節點的API服務。Flask是一個輕量級的Web框架,具有簡單易用、靈活可擴展的特點。通過Flask可以快速搭建出用于任務分配和狀態報告的API接口,滿足分布式爬蟲系統中主從節點之間的通信需求。
(三)消息隊列
選擇RabbitMQ作為消息隊列。RabbitMQ是一個開源的、高性能的消息代理軟件,支持多種消息協議,具有高可靠性、高擴展性和高可用性。在分布式爬蟲系統中,使用RabbitMQ可以實現任務的異步分發和結果的異步收集,解耦爬蟲任務的生產和消費過程,提高系統的整體性能和穩定性。
(四)數據存儲
- 數據采集階段:在數據采集過程中,對于臨時存儲采集到的數據,采用文件存儲方式(如FileStorage將數據存儲在data.json文件中)。這種方式簡單直接,適用于數據量較小、對讀寫性能要求不是特別高的場景。
- 數據長期存儲與管理:對于長期存儲和管理大量數據,選用MongoDB數據庫。MongoDB是一個面向文檔的NoSQL數據庫,具有靈活的數據模型、高擴展性和高讀寫性能。它能夠很好地適應爬蟲系統中數據結構多樣、數據量快速增長的特點,方便進行數據的插入、查詢和更新操作。
(五)輔助工具
- 代理池:使用自定義的ProxyPool工具。在爬蟲過程中,為了避免被目標網站封禁IP,需要使用代理IP。ProxyPool可以實現代理IP的獲取、驗證和管理,為爬蟲提供穩定可靠的代理IP資源。
- Robots協議檢查器:利用RobotsChecker工具檢查目標網站的Robots協議。遵守Robots協議是爬蟲合法合規運行的基礎,RobotsChecker能夠根據目標網站的Robots協議規則,判斷是否可以對特定頁面進行爬取,避免違反網站規定。
三、相關開發文檔
(一)技術文檔
- 系統架構設計文檔:詳細描述分布式爬蟲系統的整體架構,包括主節點、從節點、消息隊列、數據存儲等各個組件的功能和交互關系。通過架構圖和文字說明,使開發人員對系統的整體框架有清晰的認識,便于進行后續的開發和維護工作。
- 模塊設計文檔:針對每個功能模塊(如URLManager、DataCrawler、DataStorage等),編寫詳細的模塊設計文檔。文檔內容包括模塊的功能概述、輸入輸出接口、內部實現邏輯、關鍵算法和數據結構等。這有助于開發人員深入理解每個模塊的功能,提高代碼開發的準確性和效率。
- 數據庫設計文檔:如果使用數據庫(如MongoDB)進行數據存儲,需要編寫數據庫設計文檔。文檔中應包含數據庫的架構設計、集合(表)結構設計、索引設計、數據存儲策略等內容。這對于保證數據庫的性能和數據的一致性非常重要。
(二)使用文檔
- 安裝部署文檔:提供詳細的項目安裝和部署步驟,包括Python環境的搭建、依賴庫的安裝、項目代碼的部署、消息隊列和數據庫的配置等。確保開發人員和運維人員能夠按照文檔順利完成項目的部署工作。
- 使用指南:編寫用戶使用指南,介紹如何啟動分布式爬蟲系統,如何配置爬蟲任務(如設置爬取的URL列表、爬取深度等參數),如何查看爬蟲任務的運行狀態和結果等。這有助于用戶快速上手使用分布式爬蟲系統。
(三)測試文檔
- 測試計劃文檔:制定詳細的測試計劃,包括測試目標、測試范圍、測試策略、測試資源安排、測試進度計劃等內容。明確測試的重點和難點,合理安排測試資源和時間,確保測試工作的順利進行。
- 測試用例文檔:根據項目的功能需求和設計文檔,編寫詳細的測試用例。測試用例應覆蓋系統的各個功能模塊和關鍵業務流程,包括功能測試、性能測試、兼容性測試等方面。通過執行測試用例,可以發現系統中存在的缺陷和問題,及時進行修復和優化。
3.2 架構設計
可以補充場景分析環節,明確要解決的問題和前提假設,比如預計0.5%的用戶屬于大V,粉絲很多,也會經常上傳視頻,當前架構的解決方案是xxx。 |
一、場景分析
(一)要解決的問題
- 高效大規模數據采集:互聯網上海量的網頁數據是本項目的采集目標,需快速、全面地獲取。傳統單節點爬蟲面對大規模數據時效率極低,無法滿足數據需求,且在采集過程中容易因網絡波動、網站反爬機制等問題中斷,導致數據采集不完整。
- 應對網站反爬策略:眾多網站設置了多種反爬機制,如IP限制、User - Agent檢測、驗證碼驗證等。爬蟲需具備應對這些反爬策略的能力,否則頻繁被封IP或禁止訪問,會嚴重影響數據采集工作。
- 分布式任務調度與協同:實現多節點的高效協作,合理分配爬蟲任務。避免出現任務分配不均的情況,防止部分節點負載過高而部分閑置,同時要確保任務在節點間可靠分發與狀態跟蹤,保障任務順利完成。
- 數據的有效存儲與管理:采集到的大量數據需進行妥善存儲和管理,方便后續處理、分析與查詢。要保證數據的安全性和完整性,避免數據丟失或損壞,且在數據量不斷增長的情況下,存儲系統仍能高效運行。
- 系統的高穩定性與擴展性:系統需長時間穩定運行,能應對網絡波動、節點故障等突發狀況。隨著業務發展,數據采集規模擴大,系統要便于擴展,可靈活增加爬蟲節點或存儲資源。
(二)前提假設
- 數據規模假設:預計初期每天需采集的數據量約為5GB,數據類型主要為網頁文本、少量圖片和鏈接信息。隨著業務拓展,數據量將以每月15%的速度增長。
- 硬件資源假設:每個爬蟲節點服務器配置為4核CPU、8GB內存、500GB硬盤,網絡帶寬為50Mbps。存儲服務器配置為8核CPU、16GB內存、2TB硬盤,網絡帶寬為100Mbps。
- 網絡環境假設:項目運行在相對穩定的網絡環境中,但可能受外部網絡(如目標網站所在網絡)不穩定因素影響,存在一定網絡延遲和丟包率。
- 網站反爬假設:假設約30%的目標網站存在一定程度的反爬機制,其中10%的網站反爬機制較為復雜,需要采用多種策略應對。
(三)當前架構解決方案
- 針對高效大規模數據采集:采用分布式爬蟲架構,多節點并行工作,提高數據采集效率。通過URL管理器統一管理待爬取URL,合理分配任務到各個爬蟲節點,實現高效的數據采集。
- 應對網站反爬策略:利用代理池獲取大量代理IP,定期更換IP地址,規避IP限制。同時,在請求頭中設置多樣化的User - Agent,模擬不同的訪問終端。對于驗證碼驗證,考慮引入第三方驗證碼識別服務或開發智能識別算法。
- 分布式任務調度與協同:使用消息隊列(如RabbitMQ)實現任務異步分發和結果異步收集。主節點將任務發送到消息隊列,從節點從隊列中獲取任務并執行,完成后將結果返回。主節點通過消息隊列監控任務狀態,進行任務重試和調度優化。
- 數據的有效存儲與管理:根據數據量和業務需求,初期采用文件存儲(如FileStorage將數據存儲在data.json文件中)進行臨時存儲,后期隨著數據量增長,切換到數據庫存儲(如MongoDB或MySQL)。MongoDB適合處理海量、結構靈活的數據,MySQL適合對數據一致性和事務性要求較高的場景。利用數據庫的索引、分區等技術,提高數據存儲和查詢性能。
- 系統的高穩定性與擴展性:在系統設計上,各個模塊之間相對獨立,通過接口進行交互。當某個節點出現故障時,其他節點可以繼續工作,消息隊列會暫存任務,待故障節點恢復后重新分配任務。如需擴展系統,只需增加爬蟲節點服務器和存儲服務器,調整相關配置即可。
二、架構設計
(一)整體架構概述
本分布式爬蟲系統主要由主節點、從節點、URL管理器、消息隊列、數據采集模塊、數據解析模塊、數據存儲模塊和輔助工具(代理池、Robots協議檢查器)組成。各部分協同工作,實現數據的高效采集、處理和存儲。
(二)模塊設計
- 主節點:作為整個系統的核心控制單元,負責初始化任務隊列,將種子URL添加到URL管理器中。通過Flask框架搭建API服務,提供任務分配接口(如/get_task)和任務狀態報告接口(如/report_status)。接收從節點的任務狀態報告,根據任務執行情況調整任務分配策略,確保任務的有效調度。
- 從節點:從消息隊列中獲取爬蟲任務,調用數據采集模塊、數據解析模塊和數據存儲模塊完成任務。數據采集模塊負責根據URL獲取網頁內容,數據解析模塊對采集到的網頁內容進行解析,提取有用信息,數據存儲模塊將解析后的數據保存到指定存儲介質。從節點執行完任務后,將任務狀態(成功或失敗)通過消息隊列或API報告給主節點。
- URL管理器(URLManager):使用Redis數據庫存儲URL。負責管理待爬取URL集合和已爬取URL集合。提供添加種子URL、獲取待爬取URL、添加新發現URL、獲取已訪問URL等功能。利用Redis的集合數據結構,確保URL的唯一性和高效的添加、查詢操作。
- 消息隊列(如RabbitMQ):在主節點和從節點之間傳遞任務和任務結果。主節點將任務發送到任務隊列(如crawler_tasks),從節點從任務隊列中獲取任務進行處理。從節點完成任務后,將結果發送到結果隊列(如crawler_results),主節點從結果隊列獲取任務狀態,實現任務的異步處理和解耦。
- 數據采集模塊(DataCrawler):從URL管理器獲取待爬取URL,根據配置決定是否使用代理IP訪問目標網站。檢查目標網站的Robots協議,確保合法爬取。獲取網頁內容后,傳遞給數據解析模塊,并根據任務執行情況標記URL為已訪問或失敗。
- 數據解析模塊(DataParser):對采集到的網頁內容進行解析,提取頁面標題、正文、元數據、圖片鏈接、頁面鏈接等信息。提供多種解析方法,適應不同類型網頁的解析需求,確保解析結果的準確性和完整性。
- 數據存儲模塊(DataStorage):提供多種存儲實現方式,如文件存儲(FileStorage)、MongoDB存儲(MongoDBStorage)和MySQL存儲(MySQLStorage)。根據項目需求和數據特點選擇合適的存儲方式,負責將解析后的數據保存到相應存儲介質中,并提供數據查詢和管理功能。
- 輔助工具
- 代理池(ProxyPool):負責管理代理IP資源,提供獲取代理IP的接口。定期檢查代理IP的可用性,剔除無效代理IP,確保數據采集模塊使用的代理IP有效,提高爬蟲的抗反爬能力。
- Robots協議檢查器(RobotsChecker):根據目標網站的Robots協議,檢查是否允許爬取特定URL。獲取Robots協議中規定的爬取延遲時間,控制爬蟲的訪問頻率,遵守網站的訪問規則,避免過度爬取。
(三)模塊交互流程
- 主節點啟動時,將種子URL添加到URL管理器中,并初始化消息隊列。
- 從節點啟動后,持續監聽消息隊列中的任務。當有任務時,從URL管理器獲取待爬取URL。
- 數據采集模塊使用代理IP(若配置啟用),根據Robots協議檢查結果訪問目標網站,獲取網頁內容。
- 采集到的網頁內容傳遞給數據解析模塊,解析提取相關信息。
- 解析后的數據由數據存儲模塊保存到指定存儲介質。
- 數據采集模塊根據任務執行情況標記URL狀態,并將任務結果(成功或失敗)通過消息隊列報告給主節點。
- 主節點根據任務結果調整任務分配策略,繼續分配新任務,循環執行上述流程,直至完成所有任務。
3.3 項目代碼介紹
- 主節點 API 代碼(master_api.py):基于 Flask 框架構建。/get_task接口用于從URLManager獲取待爬取 URL 并返回;/report_status接口接收爬蟲任務狀態報告,根據狀態調用URLManager相應方法標記 URL 狀態,日志記錄狀態報告信息。主程序啟動 Flask 應用,監聽0.0.0.0:5000。
- 消息隊列操作代碼(mq_operations.py):借助pika庫與 RabbitMQ 交互。send_task_to_queue將 URL 任務發送到crawler_tasks隊列;receive_task_from_queue從隊列獲取任務,實例化相關類執行爬取,根據結果調用send_result_to_queue將任務狀態發送到crawler_results隊列。
- 主程序代碼(newMain.py):使用argparse處理命令行參數。main函數根據is_master參數區分主從節點邏輯,目前主從節點邏輯部分暫未實現。實例化多個爬蟲相關類后調用data_crawler.crawl()執行爬蟲操作。
四、測試結果
- 功能測試
- 測試用例
- 測試master_api.py中/get_task接口:準備一個有等待 URL 的URLManager實例場景,發起 GET 請求到/get_task,預期返回包含有效 URL 的 JSON 數據;再準備URLManager中無等待 URL 的場景,請求后預期返回{"task": null}。
- 測試master_api.py中/report_status接口:模擬向/report_status發送 POST 請求,請求體分別設置status為success和failed,同時攜帶一個已存在于URLManager中的 URL,查看URLManager中對應 URL 的狀態是否按預期更新,并且檢查日志是否正確記錄狀態報告信息。
- 測試mq_operations.py消息隊列操作:使用消息隊列客戶端工具向crawler_tasks隊列發送一個測試 URL 任務,觀察receive_task_from_queue函數是否能正確獲取任務并調用DataCrawler進行爬取,同時檢查crawler_results隊列是否收到正確的任務狀態消息。
- 測試newMain.py主程序:分別使用--master參數和不使用該參數運行程序,檢查是否能按預期進入主節點或從節點邏輯(盡管目前部分邏輯未實現,但可檢查程序流程是否正確),并且觀察DataCrawler的crawl方法是否能被正確調用。
- 測試結果分析:如果各接口和函數按照測試用例預期執行,如接口返回正確數據、狀態更新無誤、消息隊列正常通信、主程序流程正確,那么功能測試通過。若出現如接口返回錯誤數據、狀態未更新、消息丟失、程序崩潰等問題,則功能測試不通過,需根據錯誤提示和日志信息排查代碼錯誤,如模塊導入問題、函數邏輯錯誤、配置錯誤等。
- 性能測試
- 性能分析報告:在測試環境中模擬多任務并發場景,向crawler_tasks隊列批量發送 URL 任務,使用性能測試工具(如 JMeter 等)監控系統性能。記錄系統響應時間,包括從任務發送到receive_task_from_queue獲取任務的時間、任務處理完成并返回結果的時間;統計系統吞吐量,即單位時間內處理的任務數量;監控服務器資源利用率,如 CPU、內存、網絡帶寬等。如果響應時間過長,可能是消息隊列處理速度慢、DataCrawler處理任務效率低;吞吐量低可能是系統資源瓶頸、任務處理邏輯復雜導致;資源利用率過高則表明系統在當前配置下無法高效處理任務。
- 可優化點:若消息隊列成為性能瓶頸,可考慮優化消息隊列配置,如增加隊列容量、優化消息存儲方式,或更換更高效的消息隊列系統。若DataCrawler處理任務慢,檢查handle_crawl方法中網絡請求、數據解析、存儲操作等環節,優化代碼邏輯,如使用異步請求提高網絡請求效率、優化數據解析算法、采用更高效的存儲方式(如數據庫索引優化、批量存儲等)。針對系統資源利用率高的問題,可進行硬件升級,如增加內存、更換高性能 CPU,或優化代碼減少資源消耗,如合理釋放不再使用的對象資源、優化算法減少計算量。
五、Demo 演示視頻 (必填)
項目并沒有完成很好,運行時總是bug不斷,報錯。明明有module,可還是運行不了。
[Screen Recording 2025-03-05 213351.mp4]
六、項目總結與反思
|
1.目前仍存在的問題
- 不清楚報錯點為什么會報錯,查找原因找不到。
- 主從節點邏輯部分尚未完全實現,從節點連接主節點獲取任務以及主節點初始化任務隊列的功能缺失,無法完成完整的分布式爬蟲流程。
- 代碼中部分關鍵功能的具體實現細節不明確,例如URLManager中管理 URL 的具體算法、DataCrawler中數據爬取和處理的邏輯不夠清晰,可能影響功能的穩定性和擴展性。
- 項目中使用的消息隊列(RabbitMQ)配置信息簡單,僅設置了服務器 IP,可能無法滿足高并發、大規模任務的需求,容易出現消息積壓或處理延遲的情況。
- 未對數據存儲方式進行性能優化,如FileStorage將數據存儲在data.json文件中,隨著數據量增加,文件讀寫效率可能降低,影響整體性能。
2.已識別出的優化項
(1)環境配置優化
- 編寫環境配置腳本,自動檢測并安裝項目所需的 Python 模塊,降低部署門檻,提高環境配置的準確性和效率。
- 使用虛擬環境工具(如venv或conda),將項目依賴環境進行隔離,避免不同項目間的依賴沖突,確保項目在不同環境下的可移植性。
(2)功能優化
- 完善主從節點邏輯,實現從節點向主節點獲取任務的可靠通信機制,以及主節點對任務隊列的有效管理和分配,確保分布式爬蟲系統正常運行。
- 優化URLManager和DataCrawler的代碼邏輯,提高代碼的可讀性和可維護性,例如采用更合理的數據結構存儲 URL,優化數據爬取和處理的算法,提高功能的穩定性和擴展性。
(3)性能優化
- 優化消息隊列配置,根據實際業務需求調整隊列參數,如設置合適的隊列容量、消息持久化策略等,提高消息處理的效率和可靠性。在高并發場景下,考慮使用分布式消息隊列解決方案,提升系統的吞吐量和并發處理能力。
- 改進數據存儲方式,將數據存儲從簡單的文件存儲轉換為數據庫存儲,如使用MongoDB或MySQL,利用數據庫的索引、緩存等機制提高數據存儲和查詢的性能。同時,實現數據的批量存儲和讀取,減少 I/O 操作次數,提高整體性能。
3.架構演進的可能性
(1)引入微服務架構
將項目中的各個功能模塊(如 URL 管理、數據爬取、數據存儲等)拆分為獨立的微服務,每個微服務可以獨立開發、部署和擴展。通過微服務架構,可以提高系統的可維護性和可擴展性,便于團隊成員分工協作,同時降低單個模塊故障對整個系統的影響。
(2)采用分布式存儲和計算框架
隨著數據量和任務量的增加,現有的架構可能無法滿足性能需求。可以考慮引入分布式存儲框架(如HDFS)和分布式計算框架(如Spark),實現數據的分布式存儲和并行計算,提高系統的處理能力和性能。
(3)集成自動化監控和運維系統
為了更好地管理和維護項目,可集成自動化監控和運維系統,如Prometheus和Grafana用于監控系統性能指標(如 CPU 使用率、內存使用率、消息隊列積壓情況等),Kubernetes用于自動化部署、擴展和管理容器化應用,提高系統的穩定性和可靠性。
4.項目過程中的反思與總結
(1)項目管理方面
- 在項目初期,對項目的整體規劃和需求分析不夠充分,導致項目開發過程中出現部分功能缺失、架構設計不完善等問題。在后續項目中,應加強項目前期的規劃和需求調研,確保項目目標明確、架構合理。
- 團隊成員之間的溝通協作不夠緊密,在代碼編寫過程中可能存在對功能理解不一致、代碼風格不統一等問題。今后應建立更加有效的溝通機制,定期進行團隊交流和代碼審查,確保項目開發的一致性和高效性。
(2)技術選型方面
- 在技術選型時,對部分技術的了解不夠深入,如消息隊列和數據存儲技術,導致在項目實施過程中發現性能瓶頸。在未來的項目中,應加強對技術選型的評估和調研,充分考慮技術的適用性、性能、可擴展性等因素。
- 對項目的技術難度預估不足,導致項目開發進度受到影響。在后續項目中,應更加準確地評估技術難度,合理安排開發時間和資源,確保項目按時交付。
(3)代碼編寫方面
- 代碼的注釋和文檔編寫不夠完善,部分代碼邏輯難以理解,不利于項目的維護和擴展。在今后的開發中,應注重代碼注釋和文檔編寫,提高代碼的可讀性和可維護性。
- 代碼的可測試性不足,缺乏單元測試和集成測試代碼,難以保證代碼質量和功能的正確性。在后續項目中,應建立完善的測試體系,在開發過程中及時進行測試,確保代碼質量。