# 分散式爬蟲 & 資料監控 ## Project overview [TOC] ## 需求 1. 如何快速在同時間爬取大量網站 2. 防ban - 怎麼不被網站發現我是爬蟲 3. 隱藏身分 – 讓被抓取的網站無法追蹤IP(我是誰) 4. 爬蟲管理介面(+狀態存取) 5. 去除重複網站爬取 & 存入 ## 開發概念 來自Scrapy cluster的架構,大量運用Kafka提供的broker、Producer、Consumer概念。 ![scrapy cluster](https://i.imgur.com/VmCyDTy.png) ## 模組介紹 ### Scrapy Python的開源網絡爬蟲框架,主要使用spider作為parser,可根據需求調整抓取domain、調整header、redirection等功能。 ![](https://i.imgur.com/Y823PHj.png) ### Scrapy-Redis Based on Scrapy衍生的框架,其主要修改scrapy中的scheduler,透過調整scheduler,能夠使Request pool被Redis取代,將pool使用redis做分散式。 ![](https://i.imgur.com/hC9LbJh.png) ### Kafka & Zookeeper - Zookeeper 主要用於幫助kafka做replica、負載平衡 - Kafka Kafka是由LinkedIn開發的一個分布式的Message System,由Scala實作,它具備有水平擴充和高吞吐量的能力,而隨著新版Stream功能的加入,將自已定位為一個分散式串流平台(distributed streaming platform),來提供實時資料串接(real-time pipeline)。 ### Redis - Key-Value in-memory NoSQL - 資料結構 - <b style="color: red">STRING</b>(string、integer、float) ex. {key: value} - <b style="color: red">LIST</b>(a STRING list) ex. {key: [string, string, ...]} - <b style="color: red">SET</b>(list with unique values) ex. {key:{ustring1, ustring2, …}} - <b style="color: red">HASH</b>(hash table/Dictionary) ex.{ key: {sub_key: value}} - <b style="color: red">ZSET</b>(Ordered Dictionary) ex. {key: {700:value1, 900: value2, …}} ### 資料庫 - 使用MySQL關聯式資料庫 ![圖片1](https://i.imgur.com/efgZ3cN.png) ## 介紹 & 名詞定義 ### 運作流程 1. 統一蒐集URL,暫存於Redis 2. UrlCollector: 取得一定量於Redis列隊的URL,同時發布到AWS Lambda進行網頁HTML下載 3. LambdaProcessor: 回傳Lambda下載的HTML,存入Redis\(另一個Queue\)等待處理 4. HtmlConsumer: - 取得下載回存於Redis的Html\(一次只處理一個網頁\),並根據取得的資料\(Html、ParserName、該網頁的URL\),使用Parser模組丟入HTML進行解析,並回傳資訊 - 使用Generator取得Return的物件,根據物件的class, - Scrapy.Request: 新的請求網頁,callback為Parser,加入Redis等待請求 - Scrapy.items: 解析出的資料,發布到Kafka等待Consumer處理 5. DataConsumer: crawl item的Consumer,依收到的DataType決定如何儲存\(DB\) ### UrlCollector ``` 向Redis取得欲爬取的網址,並於定量後發送request ``` > 類似於原爬蟲階段的指定request ### HtmlConsumer ``` 向Redis取得由AWS lambda下載回來的Html,並進行剖析 ``` ### StatesConsumer ``` 處理Module中所記錄的state,並存入資料庫 ``` ### DataConsumer ``` 用於蒐集HtmlConsumer解析後的資料,處理後存入資料庫 ``` ### ModuleLauncher 初始時須更新最新parser程式碼,且定期更新 ## ModuleLauncher Flask框架的WEB API - 根據settings的launch_IP,紀錄此Server的服務IP,用於UI介面控制 - 運行另一個thread,負責定時向UI介面服務告知此服務仍在運行 ### API - /output: Dump此服務上各模組運行狀況 - /start_module: 運行一個新的thread,運行模組 - /stop_module: 呼叫模組的stop()方法,模組收到stop指令後跳出無限迴圈,結束此thread - /reset: 記錄正在運行的模組,停止此服務上所有正在運行的模組,並根據先前紀錄有在運行的模組,重新分配thread給模組並開始重新運行 ## UI介面 - /index - /crawl_states - /run_routine - /job_list - /get_states_list #### index - 觀看各模組狀況: 5秒ajax更新資料 #### crawl_states - 觀看各模組狀況: 5秒ajax更新資料 - 錯誤排名列表\(網站\): 5秒ajax更新資料 #### run_routine - 控制是否啟動固定時間發布任務功能 - 觀看目前有哪些爬蟲服務啟動 - 控制爬蟲服務的模組啟動或停止 #### job_list - 觀看目前有抓哪些網站 - 控制下一次網站是否要加入任務列表 - 點選parser可進入爬蟲過程紀錄 #### get_states_list - 給parser: 列出此parser的crawlid\(曾經發布過的任務\) - 給crawlid: 列出此crawlid下的任務爬蟲過程 ## 資料監控呈現 ### 即時抓取況狀\(爬蟲\) ![](https://i.imgur.com/YZwohar.png) ### 抓取網頁部屬\(控制是否抓取\) ![](https://i.imgur.com/beJlnPz.png) ### 近期抓取數量狀況 ![](https://i.imgur.com/Rqlj3F0.png) ### 即時發布文章 ![](https://i.imgur.com/JpAeSqX.png) ### 各版\[近24HR、近7日\]數量 ![](https://i.imgur.com/viXBhST.png)