樊 闖,歐陽瀚,黃 薇,李 燕
(武昌理工學院,湖北 武漢430223)
目前網上購物是一種極其普及的消費模式,然而由于網上購物平臺的價格具有臨時性與變動的不透明性,導致商家與消費者處于信息不對稱的位置。商品價格具有時效性,運用爬蟲技術可以爬取的特定時間的特定數據并圖表化,因此可以借助網絡爬蟲技術讓消費者能夠對所購商品的價格變化信息有較好的知情權,并針對爬取的不同時段的價格信息,為客戶生成一個方便觀察的價格波動走勢圖,有助于指導用戶養成理性消費習慣,該系統同時也節約了用盲目搜索比對商品信息所浪費的大量時間。
一個高可用的代理是爬蟲穩定性的保障,因此爬蟲的調度程序需要周期性保持穩定更新IP 代理池。為了保證爬蟲的可用性,需要合理的監控程序,才能保證爬蟲有效運行。文本結構信息是一個不太穩定隨時在更改的結構,導致爬蟲穩定需要高度依賴人進行維護。人工對程序進行問題排查效率偏低且耗費大量人力,因此良好的模塊化異常捕獲和及時地發現程序運行的異常是維護爬蟲穩定性的關鍵。
Web 服務大體分為三個模塊。分別為用戶模塊,負責用戶的登陸管理、注冊;個人信息的管理模塊;價格查詢模塊。在主體的價格查詢模塊中,可以查詢京東商城書籍信息,并且可以對其進行訂閱和收藏,訂閱的用戶可以收到商品價格變動的通知。管理員模塊可以實現用戶管理及監控爬蟲系統。
網絡爬蟲系統是為了有效率的獲取價格數據,減少人工手動收集的繁瑣過程而實現的。其主要模塊分為三個模塊,一個是主要的對京東數據的爬取模塊,包括數據下載和解析功能。二是為京東爬蟲進行支持的代理IP 池模塊,它負責動態的維護一個可用的IP 池。最后一個是負責對整個爬蟲進行調度的調度模塊,負責分發任務,定時增量更新數據等調度任務。
本系統的數據庫設計中針對爬取出來的商品的歷史價格,將其序列化到一個字段進行存儲;用戶與商品信息有兩個多對多的關系,任意用戶可以收藏任意個商品,某個商品也可以被任意多個用戶關注收藏,用戶和商品是多對多的表關系。
系統采用Django 框架進行爬蟲模塊的設計,通過WSGI(Web Server Gateway Interface)與Web 服務器通信。框架中的ORM 建立起數據模型到關系型數據庫的映射,將每個表都映射到一個Python 類對象,每條數據則被映射為一個模型類的實例對象。Template 模塊用來輸出頁面響應,將來自model數據渲染成為網頁。當接受到一個URL,控制器根據正則表達式去匹配URLconfs。根據規則將請求分配給對應的視圖函數,如果需要調度數據庫,視圖函數不會直接操作數據庫,而是會去操作對應數據模型,數據模型通過ORM 與真實的數據庫保持映射關系,數據經過數據模型層處理后,得到的信息經過Template,Template 對數據進行渲染最終生成完整的HTML 頁面。
在商品信息相關模塊中使用輕量級的Bootstrap 做為前端框架,Django 做為后端框架。搜索關鍵字通過使用ElasticSearch 倒排索引的數據結構來存儲數據,對所有商品名進行中文分詞,建立快速搜索索引,可以遠快于直接對關系型數據庫like 操作符的搜索效率。商品信息圖的繪制采用了后臺的Plotly 繪圖庫來渲染繪制HTML 形式的統計圖表,再由Django 的Template 將圖標并入到網頁模版中返回給用戶。此方式雖然加大了服務器的壓力,但瀏覽器的加載過程用戶體驗好。
后端管理員模塊使用的是Django 原生的admin APP。該工具簡潔快速的實現了對網站數據的修改查閱和更新,同時也能對用戶本身的信息進行更新,Django 基于其本身的model 來快速的構建后端管理模塊,通過簡單的配置就可以自動的生成后端頁面,既能方便對數據進行修改,同時也能做到用戶級別的后臺權限管理。
網絡爬蟲的工作流程由代理IP 池模塊、商品信息抓取模塊、商品價格抓取模塊組成。
代理IP 池模塊有兩類獨立的周期性任務,一類爬蟲負責周期性的從多個提供免費代理IP 的網站抓取有效的代理IP。爬蟲將IP 信息從網頁中進行提取,并且對代理IP 進行驗證是否生效,將無效的代理IP廢棄掉,有效的代理IP 存入Redis 中,并設置時間為一天的生命周期,這些爬蟲在每天固定時間進行代理IP 采集。另一類程序則以更頻繁的頻率對代理IP 池中的代理IP 進行測試,篩掉無效或延遲太久的代理IP,避免主爬蟲因為這些無效或者抵消的代理IP 影響爬取速度,同時根據代理IP 的延遲信息對代理IP進行評分,評分信息也會儲存在Redis 中,主爬蟲可以根據IP 的評分,優先采用優質的代理IP。
商品信息抓取模塊的爬蟲主要負責增量的抓取商品信息。在避免爬取重復的數據同時也要保證盡可能實時同步到京東商城的商品數據。程序將每次發出HTTP request 的信息保存成為指紋,指紋使用Redis 中的set 類型進行存儲,每次爬取網頁之前都會進行指紋的計算,如果指紋已經存在于Redis中了,那么該次請求將會直接丟棄,每次請求處理成功會將指紋存于Redis 中。從而實現了商品信息的增量更新。
商品價格抓取模塊會周期性的監控數據庫中的商品價格信息。由于價格接口有嚴格的反爬蟲策略,需要依賴大量的代理IP 來對價格接口進行訪問,該模塊的爬蟲從商品信息表中獲得商品ID,不斷添加商品在某個時間點的固定價格。
網絡爬蟲技術保障了數據來源的穩定可靠,多個爬蟲分布式協同工作,爬蟲之間使用Redis 作為通信中間件,在Celery 的調度之下,爬蟲有序的周期性的被調度。整個系統保持了一個松散的結構,保證了架構設計上的低耦合,同時在Celery 的管理之下整個爬蟲系統又保證了爬蟲的協同調度。