文/ 鄧子云
全國有不少物流行業協會、學會網站,會經常發出各種行業資訊,能否有一種數據收集軟件能自動收集這些資訊供公共使用呢?這樣,物流行業人士不必為查找每一個網站而費時費力,而只需要在一處查閱收集后的所有資訊。有了這種自動收集工具,還可以在收集到數據后作大數據分析,進而形成更多的行業應用,如可作物流行業的輿情分析、熱點分析、網站活躍度分析等。這些應用的前提就是要研發出具有自動收集物流資訊網站內容功能的爬蟲系統。
現已有不少相對成熟的爬蟲系統框架,如Crawler4j、Scrapy等。Crawler4j和Scrapy分別支持用Java語言、Python語言開發爬蟲系統,均支持多線程爬取數據,且均為開源系統。已有許多應用系統基于這些框架編寫,如物流車貨源信息的抽取系統、農業網絡空間信息系統等。為確保爬蟲系統的成熟和穩定,這里不打算研發新的爬蟲系統框架,而是使用現有成熟、開源的Scrapy框架技術來研發出物流資訊網站群的爬蟲系統。

圖1 物流資訊網站群爬蟲系統的功能設計

圖2 物流資訊網站群爬蟲系統的技術架構

表1 設計的MySQL的數據庫表及對應的數據項

圖3 爬蟲類CrawlPagesSpider的回調函數解析response的過程
采用Scrapy框架來研發物流資訊網站群爬蟲系統與不采用框架技術研發該系統有很大區別。首先應從業務需求和設計的角度分析設計上考慮的偏重之處,其次應分析清楚系統的技術架構,然后再予以實現。
從業務需求的角度來看,爬蟲系統需要將網頁內容、網址等信息先爬取下來保存到數據庫里。爬取網頁時需要注意限定爬取的網頁范圍為物流資訊類網站中的網頁,且不爬取網頁以外的其它文件(如圖片、PDF、Word文檔等)。由于在收集物流資訊的時效上不要求實時更新,因此在功能實現上應先做全站爬取,再定時和在需要的時候做增量爬取,增量爬取的定時間隔可控制在1天。
從設計的角度來看,Scrapy框架已將待爬取隊列、已爬取隊列、網頁查重、多線程爬取等爬蟲需要實現的通用功能實現,在物流資訊網站群爬蟲系統中重點要實現異常處理、爬蟲偽裝、數據庫操作等功能。
因此,根據物流資訊網站群爬蟲系統的業務需求和設計上的偏重,可作如圖1所示的功能設計。
物流資訊網站群爬蟲系統的技術架構如圖2。圖中綠色部分是需要開研發的模塊,其它部分是Scrapy已有的模塊,這些不需再行研發。
從技術架構來看,下載器、調度器、核心引擎、隊列這些Scrapy都已經實現,但應研發以下模塊:
(1)網頁數據庫。這里用MySQL實現,用表存儲數據。存儲網頁數據用一個表LogisticsWebPage就可實現。使用MySQL的原因是因為這種數據庫開源,可支持大容量數據的存取和并發訪問,并且具有良好的操作系統可移植性,Windows平臺、Linux和Unix平臺都可適配。
(2)數據項。需要定義一個數據項類,這個類對應于MySQL中存儲數據的表。為簡單起見,這里用一個數據項類LogisticsWebPageItem對應數據庫中的表LogisticsWebPages,數據項類的一個屬性對應表中的一列,這樣一個LogisticsWebPageItem對象就對應著表LogisticsWebPages中的一條記錄。
(3)網站群爬蟲。對于網站群的全站爬取和增量爬取,只需要研發一個爬蟲類CrawlPagesSpider。增量爬取功能的實現不需要再行編制程序,在運行爬蟲的命令中加入網頁查重配置參數即可。這是因為Scrapy已經實現了網頁查重功能,應用哈希技術記錄了已經訪問過的網頁,在再次啟動爬蟲時Scrapy會自動判斷網頁是否已經下載過,如沒有下載過則爬取,如已下載過則略過。Scrapy按URL(Uniform Resource Locator,統一資源定位器)、POST數據、Method這3項來判斷網頁是否已下載過,如果這3項合起來做哈希運算可找到記錄的相同項則表示已下載過。這種網頁查重辦法已可適用于物流資訊網站群爬蟲系統的需求。
(4)項目管道。需要在項目管道中編制程序,將數據項用insert SQL語句把網頁數據存儲到MySQL數據庫中。
(5)2個中間件。需要研發異常處理中間件ExceptMiddleware和偽裝中間件AgentMiddleware。異常處理中間件ExceptMiddleware用于處理下載過程中產生的所有異常,包括超時異常、域名解析異常等,以增強爬蟲系統的健壯性、穩定性和保持一定的爬取速度,不至于在下載引發異常時,部分線程中斷、無限等待和向Scrapy容器拋出未處理的異常。偽裝中間件AgentMiddleware用于防止物流資訊網站拒絕爬取,可以采用偽裝瀏覽器和使用代理服務器2種方法,經過考察發現物流資訊網站絕大多數沒有反爬蟲系統,因此這里采用簡單的隨機偽裝各種瀏覽器的辦法。
(6)Scrapy配置。需要修訂Scrapy的配置參數文件setting.py,用于將研發的中間件、數據項類配置進Scrapy容器,并設置下載超時時間、數據庫連接、日志水平等參數。
根據物流資訊網站群爬蟲系統的技術架構設計,下面詳細討論研發的網頁數據庫、數據項、網站群爬蟲、項目管道、2個中間件、Scrapy配置的實現。
設計的MySQL的數據庫表及對應的數據項如表1。為防止亂碼數據的產生,在創建表時,應將字符集設置為“utf8”,即在“create table”語句的最后加上參數“DEFAULT CHARSET=utf8”。
為兼容網址為文件(如圖片、PDF、Word文檔等)的情況,當爬蟲遇到這樣的文件時,只記錄網址、網站、爬取時間,但不記錄文件內容,這樣仍可通過Scrapy的查重功能防止重復訪問這些網址。此外,由于默認情況下,MySQL支持的SQL語句最長為1M,考慮到網頁源代碼的長度可能超過1M而會引發異常,可使用MySQL的“set global”語句修改“max_allowed_packet”值為更大的值,這里將其設置為“1024*1024*32”(即32MB)。
在設計完數據項類LogisticsWebPageItem后,應修改Scrapy的配置參數文件setting.py,加入以下配置以將數據項類配置進Scrapy容器:

爬蟲類CrawlPagesSpider繼承自Scrapy的CrawlSpider類,有兩個固定的屬性需要設置。一個屬性是allowed_domains,是指允許爬蟲訪問的域名,為一維數組,這里應設置為管理員維護的物流資訊網站的域名集。另一個屬性是start_urls,表示要爬取的網站首頁,為一維數組,這里應設置為管理員維護的物流資訊網站的首頁網址。
在爬蟲類CrawlPagesSpider的回調函數中應根據response對象解析出要存儲的數據到數據項Item中,再返回這個Item,這個過程如圖3。
首先應判斷response對象看是否有下載異常,判斷的根據是異常處理中間件設置的url值,如果為空則表示有異常,繼而放棄下載和重試。如果沒有異常,繼續判斷response對象的內容是否為物流資訊類網頁,判斷的根據是response.encoding值,如果存在則為物流資訊類網頁,繼而設置數據項中的網址、標題和網頁內容。其中,標題可以用Xpath從response.text中獲取。如果獲得response.encoding值引發了異常(圖片、PDF、Word文檔等非網頁類文件的response對象沒有encoding值),則判斷為非物流資訊類網頁,在數據項中只填入網址,而不設置網頁標題和網頁內容。
在爬蟲類CrawlPagesSpider的回調函數中不應操作數據庫,操作數據的工作應放在項目管道中完成。
項目管道類LogisticsWebPipeline的工作內容是:從Scrapy配置文件setting.py中獲得數據庫連接參數并設置數據庫連接池的連接參數;從數據庫連接池中獲得一個連接;根據數據項生成一個insert SQL語句;執行insert SQL語句;及時捕獲以上工作中的異常,并作出日志記錄。
根據圖2所示的技術架構,設計了2個中間件,一個為異常處理中間件,另一個為偽裝中間件,其實現原理均比較簡單,不作贅述,但應在Scrapy中作出配置:

在setting.py配置文件需要配置的參數中,前述已經給出了項目管道和中間件的配置,不再贅述,但還應給出如表2所示的配置參數,以優化爬蟲的性能。
在以上參數的設置上,爬取的并發數應視爬蟲系統所在的計算機性能而定,默認值為32,這里因采用了較高性能的服務器而設置為100;將COOKIES_ENABLED和RETRY_ENABLED參數設置為False,可提升爬蟲的性能,以免反復去嘗試下載某個網頁;將DOWNLOAD_TIMEOUT設置為80是考慮到在可接受的80秒以內下載完一個網頁,以免下載網頁的線程進入太長時間的等待而降低整個爬蟲系統的性能。
物流資訊網站群爬蟲系統使用了2臺服務器,已經對10個物流資訊類網站作了全站爬取和增量爬取,具體情況分析如下。
物流資訊網站群爬蟲系統使用了1臺爬蟲服務器和1臺數據庫服務器,這2臺服務器的軟硬件環境及網絡環境如表3,2臺服務器均放置于本文作者所在單位的中心機房。
經過對中國物流與采購聯合會(www.chinawuliu.com.cn)、江西省物流與采購聯合會(www.jiangxiwuliu.com.cn)、北京物流協會(56beijing.org)等10個網站的爬取,實驗中一共爬取了858,523個網頁,花去了1791.25分鐘(29.85小時),存儲數據庫共占用21,413MB空間,其分布情況如圖4。

表2 setting.py配置文件中的其它配置參數

表3 軟硬件環境及網絡環境

圖4 從10個物流資訊網站爬取的網頁數量圖5 不同線程數爬蟲的爬取速度

其中,從中國物流與采購聯合會網站爬取了556,932個網頁,從北京物流協會網站爬取了263,356個網頁,從這兩個網站爬取的網頁數量占到總數的95.6%,可見資訊信息相對比較集中。
以爬取前20萬個網頁為例,計算爬取網頁的平均速度,平均速度變化如圖5所示。速度的計算公式如(公式1)所示。

式1中,s表示累積爬取的時間,n表示累積爬取的網頁數量。
從圖5來看,爬取速度峰值達到了22.3個/秒,還可以發現一些規律:線程數越多,爬取速度越快;線程數設置為10和100個速度差距并不明顯;在爬取到12萬個網頁左右,爬蟲爬取速度均呈下降趨勢。可見,在采用10個以上的線程并行爬取后,增加線程數并不能顯著提升爬蟲的性能。
根據對基于Scrapy的物流資訊網站群爬蟲系統的需求分析和技術架構設計,應重點研發該系統的網頁數據庫、數據項、網站群爬蟲、項目管道、2個中間件、Scrapy配置等模塊。應用該爬蟲系統已經爬取了10個物流資訊類網站的85.85萬個網頁。從實驗情況來看,中國物流與采購聯合會、北京物流協會網站的信息量較大,兩者占比合計達到95.6%;增加線程數并不能明顯加快爬取的速度,并發線程數設置為10即可。從爬蟲的爬取速度來看,還需要做出優化處理,應爭取把爬蟲性能提升到100萬個/天以上;爬取的物流資訊類網站數量太少,應擴大到100個以上。后續還將繼續展開以下研究:
1.優化爬蟲,加大爬取的物流資訊類網站數量。從一次性提交多個SQL語句、調優爬蟲性能參數等方面繼續提升爬蟲性能。
2.研發大數據分析與展示平臺。繼續開發程序清洗下載的海量網頁數據,提取出網頁結構和文字內容,采用TensorFlow對下載的海量的網頁作分詞、詞頻等技術處理,在Web系統中展示大數據與人工智能分析的結果,供物流行業廣泛使用。