陸亮 李東
摘要:分析了Web2.0網(wǎng)絡(luò)的網(wǎng)絡(luò)爬蟲面臨的新挑戰(zhàn),對(duì)目前學(xué)術(shù)界出現(xiàn)的多種實(shí)現(xiàn)方案和策略進(jìn)行了全面的綜述,提出了AJAX爬蟲的設(shè)計(jì)并加以實(shí)現(xiàn),最后進(jìn)行了實(shí)驗(yàn)驗(yàn)證,驗(yàn)證了這種AJAX Crawler能夠很好地獲取AJAX的動(dòng)態(tài)頁面,并與普通的爬蟲在下載速度方面進(jìn)行了對(duì)比。
關(guān)鍵詞:動(dòng)態(tài)網(wǎng)頁; AJAX; Web2.0; 網(wǎng)絡(luò)爬蟲
中圖分類號(hào):TP393 文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):2095-2163(2013)06-0057-04
0引言
Web2.0是相對(duì)Web1.0的新一代互聯(lián)網(wǎng)應(yīng)用的統(tǒng)一名稱。Web1.0的重要特征是用戶通過使用瀏覽器獲取靜態(tài)的網(wǎng)絡(luò)信息。Web2.0則側(cè)重于用戶與用戶之間的交流和溝通,用戶不僅作為網(wǎng)頁內(nèi)容的查看者,同時(shí)也是網(wǎng)頁內(nèi)容的創(chuàng)造者。所說的網(wǎng)頁內(nèi)容的創(chuàng)造者是指互聯(lián)網(wǎng)上的所有用戶不再只是互聯(lián)網(wǎng)內(nèi)容的讀者,同時(shí)也成為了互聯(lián)網(wǎng)內(nèi)容的作者;不再僅是沖浪于互聯(lián)網(wǎng)海洋之中,同時(shí)也是海洋波浪的制造者;在模式上由純粹的“只讀”變?yōu)椤白x寫”進(jìn)而發(fā)展成為“共同建設(shè)”;由簡(jiǎn)單被動(dòng)地接收互聯(lián)網(wǎng)信息轉(zhuǎn)變?yōu)橹鲃?dòng)創(chuàng)造互聯(lián)網(wǎng)信息,從而增加了互動(dòng),更加符合用戶的使用習(xí)慣。
近年來,隨著Web2.0的興起,在Web開發(fā)中運(yùn)用AJAX技術(shù)的網(wǎng)站越來越多,這些技術(shù)的應(yīng)用帶來了更好的用戶體驗(yàn)、很多新概念和WebUI設(shè)計(jì),同時(shí),由于AJAX技術(shù)可以動(dòng)態(tài)改變頁面內(nèi)容,改造了傳統(tǒng)Web頁面的結(jié)構(gòu),導(dǎo)致單純抓取靜態(tài)Web頁面的網(wǎng)絡(luò)爬蟲抓取的內(nèi)容少于頁面呈現(xiàn)的內(nèi)容,這些動(dòng)態(tài)內(nèi)容給網(wǎng)絡(luò)爬蟲的設(shè)計(jì)帶來極大挑戰(zhàn),使得爬蟲不能獲取到網(wǎng)頁頁面所呈現(xiàn)的全部文本。
本文研究能夠支持AJAX的網(wǎng)絡(luò)爬蟲的原理,實(shí)現(xiàn)一個(gè)支持AJAX且能夠進(jìn)行定制任務(wù)的網(wǎng)絡(luò)爬蟲,高效率地對(duì)網(wǎng)頁信息進(jìn)行采集。第1節(jié)介紹國(guó)內(nèi)外對(duì)AJAX頁面的抓取研究情況,第2節(jié)介紹支持AJAX的爬蟲的設(shè)計(jì)及具體實(shí)現(xiàn),第3節(jié)通過實(shí)驗(yàn)驗(yàn)證了支持AJAX的爬蟲的可行性。
1相關(guān)工作
現(xiàn)階段,主流的搜索引擎,例如:Yahoo!和Google等,都無法對(duì)AJAX動(dòng)態(tài)網(wǎng)頁建立索引,也就是說不能利用現(xiàn)有的搜索引擎來查詢動(dòng)態(tài)網(wǎng)頁的內(nèi)容。而能夠支持AJAX的搜索引擎還處于研究階段,羅兵使用基于協(xié)議的動(dòng)態(tài)頁面抓取方法,獲取AJAX網(wǎng)頁內(nèi)包含的JavaScript代碼片段,通過設(shè)計(jì)腳本語言解釋器直接分析腳本代碼,仿照瀏覽器功能順序執(zhí)行腳本文件,用來模擬頁面的狀態(tài)轉(zhuǎn)換[1],肖卓磊在之后的研究中也采用了類似的處理方法[2];曾偉輝、李淼利用切片算法構(gòu)造了程序?qū)哟文P?,解決了有序執(zhí)行JavaScript腳本的問題[3];Frey[4]和Matter[5]改進(jìn)了開源的JavaScript解釋器Rhino[6],用來實(shí)現(xiàn)狀態(tài)轉(zhuǎn)換和腳本執(zhí)行。實(shí)現(xiàn)全部功能的腳本解釋器較為困難,即便是已開發(fā)多年的Rhino項(xiàng)目,依舊有很多的腳本代碼不能正常執(zhí)行,于是,更多的研究人員將研究重點(diǎn)落定于嵌入式瀏覽器組件,運(yùn)用組件來模擬AJAX頁面的渲染并實(shí)現(xiàn)腳本的執(zhí)行,以達(dá)到自動(dòng)轉(zhuǎn)換狀態(tài)的目的;在國(guó)內(nèi),采用類似方法研究的是王映[7]和金曉鷗[8],研究對(duì)使用網(wǎng)絡(luò)爬蟲分析腳本語言的技術(shù)進(jìn)行了一些研究,前者使用的是開源的JavaScript引擎SpiderMonkey,而后者利用的是Rhino。因其均解析了包含JavaScript腳本代碼的動(dòng)態(tài)頁面,從頁面中抓取了JavaScript代碼,由此獲得了網(wǎng)頁上的URL,并實(shí)現(xiàn)了內(nèi)容爬取。Frey和Matter擴(kuò)展了Cobra工具集[9],完成了動(dòng)態(tài)解析和加載HTML代碼,然后在內(nèi)部形成DOM結(jié)構(gòu)樹,并通過DOM樹獲取狀態(tài)包含的內(nèi)容。類似于狀態(tài)轉(zhuǎn)換問題,為了最大限度地利用現(xiàn)有的技術(shù),多數(shù)的狀態(tài)內(nèi)容獲得方式是采用嵌入瀏覽器組件作為運(yùn)行AJAX容器,并使用瀏覽器的外部接口實(shí)現(xiàn)和DOM樹的數(shù)據(jù)交互,由此而獲得完整的內(nèi)容[10-13]。
在控制轉(zhuǎn)換方面,較為常用的方式是采用事件過濾機(jī)制,對(duì)已經(jīng)過濾后的事件逐一進(jìn)行觸發(fā)。為了提高執(zhí)行效率,Xia[12]和Duda[14]均提出讓用戶能夠自定義過濾規(guī)則,也就是加入拒絕規(guī)則和接收規(guī)則,如此即使得只有在符合規(guī)則的集合里才能進(jìn)行狀態(tài)轉(zhuǎn)換;Mesbah等采用面向領(lǐng)域的手工配置、HTML元素注解和全自動(dòng)掃描三種方式來對(duì)狀態(tài)轉(zhuǎn)換進(jìn)行控制[10];Matter則提出了一種啟發(fā)式的爬行策略,盡量避免從不同路徑進(jìn)入相同的頁面狀態(tài)[5]。
2AJAXCrawler爬蟲設(shè)計(jì)方案及實(shí)現(xiàn)
由于Web 2.0的流行,使用AJAX技術(shù)的網(wǎng)站越來越多,本文采用了Rhino引擎對(duì)AJAX進(jìn)行了支持。
2.1 JavaScript引擎Rhino
Rhino采用Java語言實(shí)現(xiàn)的JavaScript腳本引擎。Rhino用在Java程序中,為最終用戶提供腳本化能力。Rhino包含JavaScript編譯器、JavaScript解析器、JavaScript調(diào)試等模塊。下面即對(duì)腳本編譯模塊和腳本解釋模塊進(jìn)行全面分析。
2.1.1腳本編譯模塊
編譯器的輸入是JavaScript代碼,輸出是JavaScript數(shù)據(jù)對(duì)象。JavaScript結(jié)構(gòu)中包含了字節(jié)碼、注釋、string池、數(shù)據(jù)以及標(biāo)識(shí)符。JavaScript中還包含Objects,函數(shù)等。其中,函數(shù)也是一段嵌套的JavaScript代碼。編譯器由以下三部分組成:隨機(jī)邏輯(randomlogic)的詞法掃描器,用來創(chuàng)建AST的遞歸下降分析器,tree‐walking代碼生成器。編譯過程是由函數(shù)Main.processSource()來完成的,將輸入的字符串或者JavaScript代碼轉(zhuǎn)化成流文件進(jìn)行編譯。在編譯過程中,所有的變量,符號(hào)以及命令等都由詞法分析器進(jìn)行解析,再利用內(nèi)部特定的符號(hào)標(biāo)識(shí),放入對(duì)應(yīng)的數(shù)據(jù)棧中,最后將得到的數(shù)據(jù)用樹形結(jié)構(gòu)返回,便于Rhino引擎編譯。在少分號(hào)或者是可賦值表達(dá)式等情況下,用語義和詞法的反饋(feedback)機(jī)制來消除歧義。編譯器沒有錯(cuò)誤校正,因此,只要遇到錯(cuò)誤,就立即停止。另外,編譯器還在編譯完成的script結(jié)構(gòu)中加入sourcenotes信息,以便用戶調(diào)用toSource()函數(shù)進(jìn)行反編譯時(shí)使用。
2.1.2腳本解釋模塊
類似大多數(shù)的JavaScript引擎,Rhino的interpreter是一個(gè)單線程的大型循環(huán)函數(shù),該函數(shù)每次解釋bytecode的一個(gè)指令。在這個(gè)大型函數(shù)中,采用的是switch語句,即根據(jù)所要執(zhí)行的bytecode的不同,跳轉(zhuǎn)到不同的執(zhí)行代碼段中。大多數(shù)情況下,如果一段JavaScript代碼調(diào)用另一段JavaScript代碼,則引擎只會(huì)使用JavaScript的??臻g,interpreter也是順序執(zhí)行的。但如果JavaScript代碼調(diào)用了java代碼,再由java代碼調(diào)用JavaScript代碼,就會(huì)引起interpreter的重入問題。需要一提的是,這個(gè)大型函數(shù)是可重入的。對(duì)于interpreter所需要的各種狀態(tài)都是通過參數(shù)的形式在interpreter函數(shù)進(jìn)入時(shí)完成傳遞的。絕大多數(shù)的狀態(tài)都保存在數(shù)據(jù)結(jié)構(gòu)Context中。因此,在Rhino里,所有的公共API接口以及大部分的函數(shù)接口中,第一位參數(shù)均是一個(gè)Context的指針。
2.2 AJAX爬蟲架構(gòu)設(shè)計(jì)
爬蟲系統(tǒng)分為兩部分,第一部分是預(yù)處理階段,這個(gè)階段實(shí)現(xiàn)URL凈化,并去除不必要抓取的URL,類似于過濾器的功能。第二部分是網(wǎng)頁真正抓取的部分,由于網(wǎng)頁下載比較耗時(shí),為了充分利用資源,此處采用了多線程。抓取階段獲得網(wǎng)頁,析出網(wǎng)頁內(nèi)部的鏈接,而后進(jìn)行預(yù)處理。并不是每個(gè)網(wǎng)頁內(nèi)部的鏈接都是需要抓取的,網(wǎng)頁內(nèi)部的鏈接可能包含以前抓取過的重復(fù)URL,Robots協(xié)議禁止抓取的URl等。CleanURLs是經(jīng)過凈化后的URL庫(kù),里面存放的都是需要抓取的URL。爬蟲的架構(gòu)如圖1所示。
2.3AJAX引擎設(shè)計(jì)
AJAX引擎提供對(duì)網(wǎng)頁中AJAX的支持,能夠?qū)W(wǎng)頁中的js代碼進(jìn)行解析、執(zhí)行,由此得到網(wǎng)頁動(dòng)態(tài)內(nèi)容。AJAX引擎架構(gòu)如圖2所示。
由圖2中可見,AJAX引擎主要有三個(gè)組成部分。對(duì)AJAX頁面的解析按照下面的順序進(jìn)行。
(1)Crawler通過HTTP請(qǐng)求,獲取需要抓取的頁面。此時(shí)的頁面是一個(gè)含有AJAX代碼的頁面,其中沒有真正的內(nèi)容;
(2)DOMBuilder對(duì)頁面進(jìn)行分析,建立DOM樹,提取出其中的JS代碼,觸發(fā)相應(yīng)的事件;
(3)將AJAX代碼送入JavaScript引擎執(zhí)行,在執(zhí)行的過程中,同時(shí)根據(jù)JS對(duì)象與HTML對(duì)象映射修改HTML對(duì)象;
(4)將執(zhí)行結(jié)果重新組合生成新的頁面內(nèi)容,返回給Crawler。
3實(shí)驗(yàn)數(shù)據(jù)結(jié)果
實(shí)驗(yàn)基于Java平臺(tái),開發(fā)環(huán)境采用Eclipse,Java虛擬機(jī)版本為JDK1.6.0,Rhino版本為1.7R2,實(shí)現(xiàn)AJAXCrawler。本文主要對(duì)AJAXCrawler進(jìn)行了吞吐量的測(cè)試,并與普通的爬蟲進(jìn)行下載速度的對(duì)比。
3.1吞吐量實(shí)驗(yàn)
吞吐量實(shí)驗(yàn)是測(cè)試AJAXCrawler數(shù)量以及每個(gè)AJAXCrawler啟動(dòng)線程數(shù)與下載速度的關(guān)系。若啟動(dòng)的AJAXCrawler或者每個(gè)AJAXCrawler中的線程數(shù)太少,則系統(tǒng)不能完全利用計(jì)算機(jī)的資源,反之則會(huì)因?yàn)閹?、?shù)據(jù)競(jìng)爭(zhēng)等而降低效率。測(cè)試機(jī)器為一臺(tái)普通PC機(jī),硬件配置以及軟件配置如表1所示。
表1服務(wù)器配置表
Tab.1 Server configuration listCPU2 * AMD Athlon(tm)ⅡX2 215 Processor 2.70GHz網(wǎng)卡100Mbps內(nèi)存2.00GB操作系統(tǒng)Windows 7JAVA環(huán)境JRE 1.6.0_24
AJAXCrawler測(cè)試任務(wù)為天涯博客,通過改變AJAXCrawler以及每個(gè)AJAXCrawler內(nèi)線程的數(shù)目,測(cè)得的數(shù)據(jù)如表2所示,繪制成折線圖,如圖3所示(單位:頁面數(shù)/10分鐘)。
由表2和圖3可以看出,在當(dāng)前的計(jì)算環(huán)境和網(wǎng)絡(luò)環(huán)境下,當(dāng)選取任務(wù)數(shù)為3,每個(gè)任務(wù)內(nèi)有3個(gè)線程的時(shí)候,系統(tǒng)運(yùn)行效率達(dá)到較優(yōu),平均每10分鐘能夠下載網(wǎng)頁1 679頁。
3.2AJAXCrawler與普通爬蟲比較實(shí)驗(yàn)
此實(shí)驗(yàn)以網(wǎng)易的評(píng)論為測(cè)試對(duì)象,分析AJAXCrawler的效率。由于普通爬蟲無法抓取到動(dòng)態(tài)內(nèi)容,此處的量化指標(biāo)不再以頁面數(shù)/10分鐘作為單位,而是選擇Kb/second作為單位。測(cè)試結(jié)果如表3所示,繪制成折線圖如圖4所示。
由表3和圖4可以看到,AJAXCrawler無論是幾個(gè)任務(wù)并發(fā)執(zhí)行,都相應(yīng)地比普通的WebCrawler下載速度慢。除去實(shí)驗(yàn)環(huán)境偶然因素外,最主要的影響因素應(yīng)該是AJAXCrawler對(duì)AJAX腳本的解析和DOM樹的更新操作。因?yàn)锳JAXCrawler在關(guān)閉掉動(dòng)態(tài)頁面支持時(shí),速度跟普通WebCrawler相差不大。圖4中的兩條線幾近平行,表明兩種爬蟲此時(shí)的加速比也相差不多。而AJAXCrawler的加速上升趨勢(shì)已開始走緩,這就說明AJAXCrawler需要更多的資源。另外,若對(duì)比下載的頁面數(shù),兩者相差了十余倍,而下載速度卻相對(duì)不是很大,進(jìn)一步說明了動(dòng)態(tài)網(wǎng)頁包含的內(nèi)容豐富。
4結(jié)束語
本文設(shè)計(jì)的能夠抓取支持AJAX動(dòng)態(tài)網(wǎng)頁的網(wǎng)絡(luò)爬蟲,在抓取動(dòng)態(tài)網(wǎng)頁方面,取得了良好的結(jié)果。與普通爬蟲相比,AJAXCrawler的下載速度稍慢,主要是對(duì)AJAX腳本的解析和DOM樹的更新會(huì)相對(duì)浪費(fèi)時(shí)間。不過,下載的頁面數(shù)與普通爬蟲相比,數(shù)量卻多出了十余倍,抓取的內(nèi)容會(huì)比普通爬蟲的內(nèi)容要豐富很多。
參考文獻(xiàn):
[1]羅兵.支持AJAX的互聯(lián)網(wǎng)搜索引擎爬蟲設(shè)計(jì)與實(shí)現(xiàn)[D].杭州:浙江大學(xué),2007.
[2]肖卓磊.基于AJAX技術(shù)的搜索引擎研究[D].武漢:武漢理工大學(xué),2009.
[3]曾偉輝,李淼.基于JavaScript切片的AJAX框架網(wǎng)絡(luò)爬蟲技術(shù)研究[J].北京:計(jì)算機(jī)系統(tǒng)應(yīng)用,2009,18(7):169-171.
[4]FREYG.Indexing AJAX Web Applications. Zurich:Swiss Federal Institute of Technology Zurich,2007.
[5]MATTERR.AJAXCrawl:Making AJAX Applications Searchable. Zurich:Swiss Federal Institute of Technology Zurich,2008.
[6]MOZILLA.Rhino:JavaScript for Java.[2009-03-22].
[7]http://www.mozilla.org/rhino/.
[8]王映,于滿泉,李盛韜.JavaScript引擎在動(dòng)態(tài)網(wǎng)頁采集技術(shù)中的應(yīng)用[J].計(jì)算機(jī)應(yīng)用,2004,24(2):33-36.
[9]金曉鷗,鐘寶燕,李翔.基于Rhino的JavaScript動(dòng)態(tài)頁面解析研究與實(shí)現(xiàn)[J].計(jì)算機(jī)技術(shù)與發(fā)展,2008,18(2).
[10]COBRA.JavaHTMLRenderer&Parser.[2009-01-19].
[11]http://lobobrowser.org/cobra.jsp.
[12]MESBAHA,BOZDAGE,VANDEURSENA.Crawling AJAX by inferring user interface state changes[C]//Proceedings of the 8th International Conferenceon Web Engineering, YorktownHeights,NJ.Washington,DC,USA:IEEE Computer Society,2008:122-134.
[13]郭浩,陸余良,劉金紅.一種基于狀態(tài)轉(zhuǎn)換圖的AJAX爬行算法[J].計(jì)算機(jī)應(yīng)用研究,2009,26(11):4266-4269.
[14]XIAT. Extracting structured data from AJAX site[C]//Proceedings of 2009 International IEEE Work shop on Database Technology and Applications, Wuhan, China.2009:259-262.