文/ 鄧子云
全國有不少物流行業(yè)協(xié)會、學(xué)會網(wǎng)站,會經(jīng)常發(fā)出各種行業(yè)資訊,能否有一種數(shù)據(jù)收集軟件能自動收集這些資訊供公共使用呢?這樣,物流行業(yè)人士不必為查找每一個網(wǎng)站而費(fèi)時費(fèi)力,而只需要在一處查閱收集后的所有資訊。有了這種自動收集工具,還可以在收集到數(shù)據(jù)后作大數(shù)據(jù)分析,進(jìn)而形成更多的行業(yè)應(yīng)用,如可作物流行業(yè)的輿情分析、熱點(diǎn)分析、網(wǎng)站活躍度分析等。這些應(yīng)用的前提就是要研發(fā)出具有自動收集物流資訊網(wǎng)站內(nèi)容功能的爬蟲系統(tǒng)。
現(xiàn)已有不少相對成熟的爬蟲系統(tǒng)框架,如Crawler4j、Scrapy等。Crawler4j和Scrapy分別支持用Java語言、Python語言開發(fā)爬蟲系統(tǒng),均支持多線程爬取數(shù)據(jù),且均為開源系統(tǒng)。已有許多應(yīng)用系統(tǒng)基于這些框架編寫,如物流車貨源信息的抽取系統(tǒng)、農(nóng)業(yè)網(wǎng)絡(luò)空間信息系統(tǒng)等。為確保爬蟲系統(tǒng)的成熟和穩(wěn)定,這里不打算研發(fā)新的爬蟲系統(tǒng)框架,而是使用現(xiàn)有成熟、開源的Scrapy框架技術(shù)來研發(fā)出物流資訊網(wǎng)站群的爬蟲系統(tǒng)。
圖1 物流資訊網(wǎng)站群爬蟲系統(tǒng)的功能設(shè)計
圖2 物流資訊網(wǎng)站群爬蟲系統(tǒng)的技術(shù)架構(gòu)
表1 設(shè)計的MySQL的數(shù)據(jù)庫表及對應(yīng)的數(shù)據(jù)項(xiàng)
圖3 爬蟲類CrawlPagesSpider的回調(diào)函數(shù)解析response的過程
采用Scrapy框架來研發(fā)物流資訊網(wǎng)站群爬蟲系統(tǒng)與不采用框架技術(shù)研發(fā)該系統(tǒng)有很大區(qū)別。首先應(yīng)從業(yè)務(wù)需求和設(shè)計的角度分析設(shè)計上考慮的偏重之處,其次應(yīng)分析清楚系統(tǒng)的技術(shù)架構(gòu),然后再予以實(shí)現(xiàn)。
從業(yè)務(wù)需求的角度來看,爬蟲系統(tǒng)需要將網(wǎng)頁內(nèi)容、網(wǎng)址等信息先爬取下來保存到數(shù)據(jù)庫里。爬取網(wǎng)頁時需要注意限定爬取的網(wǎng)頁范圍為物流資訊類網(wǎng)站中的網(wǎng)頁,且不爬取網(wǎng)頁以外的其它文件(如圖片、PDF、Word文檔等)。由于在收集物流資訊的時效上不要求實(shí)時更新,因此在功能實(shí)現(xiàn)上應(yīng)先做全站爬取,再定時和在需要的時候做增量爬取,增量爬取的定時間隔可控制在1天。
從設(shè)計的角度來看,Scrapy框架已將待爬取隊列、已爬取隊列、網(wǎng)頁查重、多線程爬取等爬蟲需要實(shí)現(xiàn)的通用功能實(shí)現(xiàn),在物流資訊網(wǎng)站群爬蟲系統(tǒng)中重點(diǎn)要實(shí)現(xiàn)異常處理、爬蟲偽裝、數(shù)據(jù)庫操作等功能。
因此,根據(jù)物流資訊網(wǎng)站群爬蟲系統(tǒng)的業(yè)務(wù)需求和設(shè)計上的偏重,可作如圖1所示的功能設(shè)計。
物流資訊網(wǎng)站群爬蟲系統(tǒng)的技術(shù)架構(gòu)如圖2。圖中綠色部分是需要開研發(fā)的模塊,其它部分是Scrapy已有的模塊,這些不需再行研發(fā)。
從技術(shù)架構(gòu)來看,下載器、調(diào)度器、核心引擎、隊列這些Scrapy都已經(jīng)實(shí)現(xiàn),但應(yīng)研發(fā)以下模塊:
(1)網(wǎng)頁數(shù)據(jù)庫。這里用MySQL實(shí)現(xiàn),用表存儲數(shù)據(jù)。存儲網(wǎng)頁數(shù)據(jù)用一個表LogisticsWebPage就可實(shí)現(xiàn)。使用MySQL的原因是因?yàn)檫@種數(shù)據(jù)庫開源,可支持大容量數(shù)據(jù)的存取和并發(fā)訪問,并且具有良好的操作系統(tǒng)可移植性,Windows平臺、Linux和Unix平臺都可適配。
(2)數(shù)據(jù)項(xiàng)。需要定義一個數(shù)據(jù)項(xiàng)類,這個類對應(yīng)于MySQL中存儲數(shù)據(jù)的表。為簡單起見,這里用一個數(shù)據(jù)項(xiàng)類LogisticsWebPageItem對應(yīng)數(shù)據(jù)庫中的表LogisticsWebPages,數(shù)據(jù)項(xiàng)類的一個屬性對應(yīng)表中的一列,這樣一個LogisticsWebPageItem對象就對應(yīng)著表LogisticsWebPages中的一條記錄。
(3)網(wǎng)站群爬蟲。對于網(wǎng)站群的全站爬取和增量爬取,只需要研發(fā)一個爬蟲類CrawlPagesSpider。增量爬取功能的實(shí)現(xiàn)不需要再行編制程序,在運(yùn)行爬蟲的命令中加入網(wǎng)頁查重配置參數(shù)即可。這是因?yàn)镾crapy已經(jīng)實(shí)現(xiàn)了網(wǎng)頁查重功能,應(yīng)用哈希技術(shù)記錄了已經(jīng)訪問過的網(wǎng)頁,在再次啟動爬蟲時Scrapy會自動判斷網(wǎng)頁是否已經(jīng)下載過,如沒有下載過則爬取,如已下載過則略過。Scrapy按URL(Uniform Resource Locator,統(tǒng)一資源定位器)、POST數(shù)據(jù)、Method這3項(xiàng)來判斷網(wǎng)頁是否已下載過,如果這3項(xiàng)合起來做哈希運(yùn)算可找到記錄的相同項(xiàng)則表示已下載過。這種網(wǎng)頁查重辦法已可適用于物流資訊網(wǎng)站群爬蟲系統(tǒng)的需求。
(4)項(xiàng)目管道。需要在項(xiàng)目管道中編制程序,將數(shù)據(jù)項(xiàng)用insert SQL語句把網(wǎng)頁數(shù)據(jù)存儲到MySQL數(shù)據(jù)庫中。
(5)2個中間件。需要研發(fā)異常處理中間件ExceptMiddleware和偽裝中間件AgentMiddleware。異常處理中間件ExceptMiddleware用于處理下載過程中產(chǎn)生的所有異常,包括超時異常、域名解析異常等,以增強(qiáng)爬蟲系統(tǒng)的健壯性、穩(wěn)定性和保持一定的爬取速度,不至于在下載引發(fā)異常時,部分線程中斷、無限等待和向Scrapy容器拋出未處理的異常。偽裝中間件AgentMiddleware用于防止物流資訊網(wǎng)站拒絕爬取,可以采用偽裝瀏覽器和使用代理服務(wù)器2種方法,經(jīng)過考察發(fā)現(xiàn)物流資訊網(wǎng)站絕大多數(shù)沒有反爬蟲系統(tǒng),因此這里采用簡單的隨機(jī)偽裝各種瀏覽器的辦法。
(6)Scrapy配置。需要修訂Scrapy的配置參數(shù)文件setting.py,用于將研發(fā)的中間件、數(shù)據(jù)項(xiàng)類配置進(jìn)Scrapy容器,并設(shè)置下載超時時間、數(shù)據(jù)庫連接、日志水平等參數(shù)。
根據(jù)物流資訊網(wǎng)站群爬蟲系統(tǒng)的技術(shù)架構(gòu)設(shè)計,下面詳細(xì)討論研發(fā)的網(wǎng)頁數(shù)據(jù)庫、數(shù)據(jù)項(xiàng)、網(wǎng)站群爬蟲、項(xiàng)目管道、2個中間件、Scrapy配置的實(shí)現(xiàn)。
設(shè)計的MySQL的數(shù)據(jù)庫表及對應(yīng)的數(shù)據(jù)項(xiàng)如表1。為防止亂碼數(shù)據(jù)的產(chǎn)生,在創(chuàng)建表時,應(yīng)將字符集設(shè)置為“utf8”,即在“create table”語句的最后加上參數(shù)“DEFAULT CHARSET=utf8”。
為兼容網(wǎng)址為文件(如圖片、PDF、Word文檔等)的情況,當(dāng)爬蟲遇到這樣的文件時,只記錄網(wǎng)址、網(wǎng)站、爬取時間,但不記錄文件內(nèi)容,這樣仍可通過Scrapy的查重功能防止重復(fù)訪問這些網(wǎng)址。此外,由于默認(rèn)情況下,MySQL支持的SQL語句最長為1M,考慮到網(wǎng)頁源代碼的長度可能超過1M而會引發(fā)異常,可使用MySQL的“set global”語句修改“max_allowed_packet”值為更大的值,這里將其設(shè)置為“1024*1024*32”(即32MB)。
在設(shè)計完數(shù)據(jù)項(xiàng)類LogisticsWebPageItem后,應(yīng)修改Scrapy的配置參數(shù)文件setting.py,加入以下配置以將數(shù)據(jù)項(xiàng)類配置進(jìn)Scrapy容器:
爬蟲類CrawlPagesSpider繼承自Scrapy的CrawlSpider類,有兩個固定的屬性需要設(shè)置。一個屬性是allowed_domains,是指允許爬蟲訪問的域名,為一維數(shù)組,這里應(yīng)設(shè)置為管理員維護(hù)的物流資訊網(wǎng)站的域名集。另一個屬性是start_urls,表示要爬取的網(wǎng)站首頁,為一維數(shù)組,這里應(yīng)設(shè)置為管理員維護(hù)的物流資訊網(wǎng)站的首頁網(wǎng)址。
在爬蟲類CrawlPagesSpider的回調(diào)函數(shù)中應(yīng)根據(jù)response對象解析出要存儲的數(shù)據(jù)到數(shù)據(jù)項(xiàng)Item中,再返回這個Item,這個過程如圖3。
首先應(yīng)判斷response對象看是否有下載異常,判斷的根據(jù)是異常處理中間件設(shè)置的url值,如果為空則表示有異常,繼而放棄下載和重試。如果沒有異常,繼續(xù)判斷response對象的內(nèi)容是否為物流資訊類網(wǎng)頁,判斷的根據(jù)是response.encoding值,如果存在則為物流資訊類網(wǎng)頁,繼而設(shè)置數(shù)據(jù)項(xiàng)中的網(wǎng)址、標(biāo)題和網(wǎng)頁內(nèi)容。其中,標(biāo)題可以用Xpath從response.text中獲取。如果獲得response.encoding值引發(fā)了異常(圖片、PDF、Word文檔等非網(wǎng)頁類文件的response對象沒有encoding值),則判斷為非物流資訊類網(wǎng)頁,在數(shù)據(jù)項(xiàng)中只填入網(wǎng)址,而不設(shè)置網(wǎng)頁標(biāo)題和網(wǎng)頁內(nèi)容。
在爬蟲類CrawlPagesSpider的回調(diào)函數(shù)中不應(yīng)操作數(shù)據(jù)庫,操作數(shù)據(jù)的工作應(yīng)放在項(xiàng)目管道中完成。
項(xiàng)目管道類LogisticsWebPipeline的工作內(nèi)容是:從Scrapy配置文件setting.py中獲得數(shù)據(jù)庫連接參數(shù)并設(shè)置數(shù)據(jù)庫連接池的連接參數(shù);從數(shù)據(jù)庫連接池中獲得一個連接;根據(jù)數(shù)據(jù)項(xiàng)生成一個insert SQL語句;執(zhí)行insert SQL語句;及時捕獲以上工作中的異常,并作出日志記錄。
根據(jù)圖2所示的技術(shù)架構(gòu),設(shè)計了2個中間件,一個為異常處理中間件,另一個為偽裝中間件,其實(shí)現(xiàn)原理均比較簡單,不作贅述,但應(yīng)在Scrapy中作出配置:
在setting.py配置文件需要配置的參數(shù)中,前述已經(jīng)給出了項(xiàng)目管道和中間件的配置,不再贅述,但還應(yīng)給出如表2所示的配置參數(shù),以優(yōu)化爬蟲的性能。
在以上參數(shù)的設(shè)置上,爬取的并發(fā)數(shù)應(yīng)視爬蟲系統(tǒng)所在的計算機(jī)性能而定,默認(rèn)值為32,這里因采用了較高性能的服務(wù)器而設(shè)置為100;將COOKIES_ENABLED和RETRY_ENABLED參數(shù)設(shè)置為False,可提升爬蟲的性能,以免反復(fù)去嘗試下載某個網(wǎng)頁;將DOWNLOAD_TIMEOUT設(shè)置為80是考慮到在可接受的80秒以內(nèi)下載完一個網(wǎng)頁,以免下載網(wǎng)頁的線程進(jìn)入太長時間的等待而降低整個爬蟲系統(tǒng)的性能。
物流資訊網(wǎng)站群爬蟲系統(tǒng)使用了2臺服務(wù)器,已經(jīng)對10個物流資訊類網(wǎng)站作了全站爬取和增量爬取,具體情況分析如下。
物流資訊網(wǎng)站群爬蟲系統(tǒng)使用了1臺爬蟲服務(wù)器和1臺數(shù)據(jù)庫服務(wù)器,這2臺服務(wù)器的軟硬件環(huán)境及網(wǎng)絡(luò)環(huán)境如表3,2臺服務(wù)器均放置于本文作者所在單位的中心機(jī)房。
經(jīng)過對中國物流與采購聯(lián)合會(www.chinawuliu.com.cn)、江西省物流與采購聯(lián)合會(www.jiangxiwuliu.com.cn)、北京物流協(xié)會(56beijing.org)等10個網(wǎng)站的爬取,實(shí)驗(yàn)中一共爬取了858,523個網(wǎng)頁,花去了1791.25分鐘(29.85小時),存儲數(shù)據(jù)庫共占用21,413MB空間,其分布情況如圖4。
表2 setting.py配置文件中的其它配置參數(shù)
表3 軟硬件環(huán)境及網(wǎng)絡(luò)環(huán)境
圖4 從10個物流資訊網(wǎng)站爬取的網(wǎng)頁數(shù)量圖5 不同線程數(shù)爬蟲的爬取速度
其中,從中國物流與采購聯(lián)合會網(wǎng)站爬取了556,932個網(wǎng)頁,從北京物流協(xié)會網(wǎng)站爬取了263,356個網(wǎng)頁,從這兩個網(wǎng)站爬取的網(wǎng)頁數(shù)量占到總數(shù)的95.6%,可見資訊信息相對比較集中。
以爬取前20萬個網(wǎng)頁為例,計算爬取網(wǎng)頁的平均速度,平均速度變化如圖5所示。速度的計算公式如(公式1)所示。
式1中,s表示累積爬取的時間,n表示累積爬取的網(wǎng)頁數(shù)量。
從圖5來看,爬取速度峰值達(dá)到了22.3個/秒,還可以發(fā)現(xiàn)一些規(guī)律:線程數(shù)越多,爬取速度越快;線程數(shù)設(shè)置為10和100個速度差距并不明顯;在爬取到12萬個網(wǎng)頁左右,爬蟲爬取速度均呈下降趨勢??梢?,在采用10個以上的線程并行爬取后,增加線程數(shù)并不能顯著提升爬蟲的性能。
根據(jù)對基于Scrapy的物流資訊網(wǎng)站群爬蟲系統(tǒng)的需求分析和技術(shù)架構(gòu)設(shè)計,應(yīng)重點(diǎn)研發(fā)該系統(tǒng)的網(wǎng)頁數(shù)據(jù)庫、數(shù)據(jù)項(xiàng)、網(wǎng)站群爬蟲、項(xiàng)目管道、2個中間件、Scrapy配置等模塊。應(yīng)用該爬蟲系統(tǒng)已經(jīng)爬取了10個物流資訊類網(wǎng)站的85.85萬個網(wǎng)頁。從實(shí)驗(yàn)情況來看,中國物流與采購聯(lián)合會、北京物流協(xié)會網(wǎng)站的信息量較大,兩者占比合計達(dá)到95.6%;增加線程數(shù)并不能明顯加快爬取的速度,并發(fā)線程數(shù)設(shè)置為10即可。從爬蟲的爬取速度來看,還需要做出優(yōu)化處理,應(yīng)爭取把爬蟲性能提升到100萬個/天以上;爬取的物流資訊類網(wǎng)站數(shù)量太少,應(yīng)擴(kuò)大到100個以上。后續(xù)還將繼續(xù)展開以下研究:
1.優(yōu)化爬蟲,加大爬取的物流資訊類網(wǎng)站數(shù)量。從一次性提交多個SQL語句、調(diào)優(yōu)爬蟲性能參數(shù)等方面繼續(xù)提升爬蟲性能。
2.研發(fā)大數(shù)據(jù)分析與展示平臺。繼續(xù)開發(fā)程序清洗下載的海量網(wǎng)頁數(shù)據(jù),提取出網(wǎng)頁結(jié)構(gòu)和文字內(nèi)容,采用TensorFlow對下載的海量的網(wǎng)頁作分詞、詞頻等技術(shù)處理,在Web系統(tǒng)中展示大數(shù)據(jù)與人工智能分析的結(jié)果,供物流行業(yè)廣泛使用。