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