網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理_第1頁(yè)
網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理_第2頁(yè)
網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理_第3頁(yè)
網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理_第4頁(yè)
網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理_第5頁(yè)
已閱讀5頁(yè),還剩32頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

網(wǎng)絡(luò)爬蟲(chóng)Java實(shí)現(xiàn)原理網(wǎng)絡(luò)爬蟲(chóng)(Spider)Java實(shí)現(xiàn)原理

\o"收藏到我的網(wǎng)摘中,并分享給我的朋友"

收藏

“網(wǎng)絡(luò)蜘蛛”或者說(shuō)“網(wǎng)絡(luò)爬蟲(chóng)”,是一種能訪問(wèn)網(wǎng)站并跟蹤鏈接的程序,通過(guò)它,可快速地畫(huà)出一個(gè)網(wǎng)站所包含的網(wǎng)頁(yè)地圖信息。本文主要講述如何使用Java編程來(lái)構(gòu)建一個(gè)“蜘蛛”,我們會(huì)先以一個(gè)可復(fù)用的蜘蛛類(lèi)包裝一個(gè)基本的“蜘蛛”,并在示例程序中演示如何創(chuàng)建一個(gè)特定的“蜘蛛”來(lái)掃描相關(guān)網(wǎng)站并找出死鏈接。

Java語(yǔ)言在此非常適合構(gòu)建一個(gè)“蜘蛛”程序,其內(nèi)建了對(duì)HTTP協(xié)議的支持,通過(guò)它可以傳輸大部分的網(wǎng)頁(yè)信息;其還內(nèi)建了一個(gè)HTML解析器,正是這兩個(gè)原因使Java語(yǔ)言成為本文構(gòu)建“蜘蛛”程序的首選。

文章后面例1的示例程序,將會(huì)掃描一個(gè)網(wǎng)站,并尋找死鏈接。使用這個(gè)程序時(shí)需先輸入一個(gè)URL并單擊“Begin”按鈕,程序開(kāi)始之后,“Begin”按鈕會(huì)變成“Cancel”按鈕。在程序掃描網(wǎng)站期間,會(huì)在“Cancel”按鈕之下顯示進(jìn)度,且在檢查當(dāng)前網(wǎng)頁(yè)時(shí),也會(huì)顯示相關(guān)正常鏈接與死鏈接的數(shù)目,死鏈接將顯示在程序底部的滾動(dòng)文本框中。單擊“Cancel”按鈕會(huì)停止掃描過(guò)程,之后可以輸入一個(gè)新的URL;如果期間沒(méi)有單擊“Cancel”,程序?qū)?huì)一直運(yùn)行直到查找完所有網(wǎng)頁(yè),此后,“Cancel”按鈕會(huì)再次變回“Begin”,表示程序已停止。

下面將演示示例程序是如何與可復(fù)用“Spider”類(lèi)交互的,示例程序包含在例1的CheckLinks類(lèi)中,這個(gè)類(lèi)實(shí)現(xiàn)了ISpiderReportable接口,如例2所示,正是通過(guò)這個(gè)接口,蜘蛛類(lèi)才能與示例程序相交互。在這個(gè)接口中,定義了三個(gè)方法:第一個(gè)方法是“spiderFoundURL”,它在每次程序定位一個(gè)URL時(shí)被調(diào)用,如果方法返回true,表示程序應(yīng)繼續(xù)執(zhí)行下去并找出其中的鏈接;第二個(gè)方法是“spiderURLError”,它在每次程序檢測(cè)URL導(dǎo)致錯(cuò)誤時(shí)被調(diào)用(如“404頁(yè)面未找到”);第三個(gè)方法是“spiderFoundEMail”,它在每次發(fā)現(xiàn)電子郵件地址時(shí)被調(diào)用。有了這三個(gè)方法,Spider類(lèi)就能把相關(guān)信息反饋給創(chuàng)建它的程序了。

在begin方法被調(diào)用后,“蜘蛛”就開(kāi)始工作了;為允許程序重繪其用戶界面,“蜘蛛”是作為一個(gè)單獨(dú)的線程啟動(dòng)的。點(diǎn)擊“Begin”按鈕會(huì)開(kāi)始這個(gè)后臺(tái)線程,當(dāng)后臺(tái)線程運(yùn)行之后,又會(huì)調(diào)用“CheckLinks”類(lèi)的run方法,而run方法是由Spider對(duì)象實(shí)例化時(shí)啟動(dòng)的,如下所示:

spider=newSpider(this);

spider.clear();

base=newURL(url.getText());

spider.addURL(base);

spider.begin();

首先,一個(gè)新的Spider對(duì)象被實(shí)例化,在此,需要傳遞一個(gè)“ISpiderReportable”對(duì)象給Spider對(duì)象的構(gòu)造函數(shù),因?yàn)椤癈heckLinks”類(lèi)實(shí)現(xiàn)了“ISpiderReportable”接口,只需簡(jiǎn)單地把它作為當(dāng)前對(duì)象(可由關(guān)鍵字this表示)傳遞給構(gòu)造函數(shù)即可;其次,在程序中維護(hù)了一個(gè)其訪問(wèn)過(guò)的URL列表,而“clear”方法的調(diào)用則是為了確保程序開(kāi)始時(shí)URL列表為空,程序開(kāi)始運(yùn)行之前必須添加一個(gè)URL到它的待處理列表中,此時(shí)用戶輸入的URL則是添加到列表中的第一個(gè),程序就由掃描這個(gè)網(wǎng)頁(yè)開(kāi)始,并找到與這個(gè)起始URL相鏈接的其他頁(yè)面;最后,調(diào)用“begin”方法開(kāi)始運(yùn)行“蜘蛛”,這個(gè)方法直到“蜘蛛”工作完畢或用戶取消才會(huì)返回。

當(dāng)“蜘蛛”運(yùn)行時(shí),可以調(diào)用由“ISpiderReportable”接口實(shí)現(xiàn)的三個(gè)方法來(lái)報(bào)告程序當(dāng)前狀態(tài),程序的大部分工作都是由“spiderFoundURL”方法來(lái)完成的,當(dāng)“蜘蛛”發(fā)現(xiàn)一個(gè)新的URL時(shí),它首先檢查其是否有效,如果這個(gè)URL導(dǎo)致一個(gè)錯(cuò)誤,就會(huì)把它當(dāng)作一個(gè)死鏈接;如果鏈接有效,就會(huì)繼續(xù)檢查它是否在一個(gè)不同的服務(wù)器上,如果鏈接在同一服務(wù)器上,“spiderFoundURL”返回true,表示“蜘蛛”應(yīng)繼續(xù)跟蹤這個(gè)URL并找出其他鏈接,如果鏈接在另外的服務(wù)器上,就不會(huì)掃描是否還有其他鏈接,因?yàn)檫@會(huì)導(dǎo)致“蜘蛛”不斷地瀏覽Internet,尋找更多、更多的網(wǎng)站,所以,示例程序只會(huì)查找用戶指定網(wǎng)站上的鏈接。

構(gòu)造Spider類(lèi)

前面已經(jīng)講了如何使用Spider類(lèi),請(qǐng)看例3中的代碼。使用Spider類(lèi)及“ISpiderReportable”接口能方便地為某一程序添加“蜘蛛”功能,下面繼續(xù)講解Spider類(lèi)是怎樣工作的。

Spider類(lèi)必須保持對(duì)其訪問(wèn)過(guò)的URL的跟蹤,這樣做的目的是為了確保“蜘蛛”不會(huì)訪問(wèn)同一URL一次以上;進(jìn)一步來(lái)說(shuō),“蜘蛛”必須把URL分成三組,第一組存儲(chǔ)在“workloadWaiting”屬性中,包含了一個(gè)未處理的URL列表,“蜘蛛”要訪問(wèn)的第一個(gè)URL也存在其中;第二組存儲(chǔ)在“workloadProcessed”中,它是“蜘蛛”已經(jīng)處理過(guò)且無(wú)需再次訪問(wèn)的URL;第三組存儲(chǔ)在“workloadError”中,包含了發(fā)生錯(cuò)誤的URL。

Begin方法包含了Spider類(lèi)的主循環(huán),其一直重復(fù)遍歷“workloadWaiting”,并處理其中的每一個(gè)頁(yè)面,當(dāng)然我們也想到了,在這些頁(yè)面被處理時(shí),很可能有其他的URL添加到“workloadWaiting”中,所以,begin方法一直繼續(xù)此過(guò)程,直到調(diào)用Spider類(lèi)的cancel方法,或“workloadWaiting”中已不再剩有URL。這個(gè)過(guò)程如下:

cancel=false;

while(!getWorkloadWaiting().isEmpty()&&!cancel){

Objectlist[]=getWorkloadWaiting().toArray();

for(inti=0;(i<LIST.LENGTH)&&!CANCEL;)i++>

processURL((URL)list[i]);

}

當(dāng)上述代碼遍歷“workloadWaiting”時(shí),它把每個(gè)需處理的URL都傳遞給“processURL”方法,而這個(gè)方法才是真正讀取并解析URL中HTML信息的。

讀取并解析HTML

Java同時(shí)支持訪問(wèn)URL內(nèi)容及解析HTML,而這正是“processURL”方法要做的。在Java中讀取URL內(nèi)容相對(duì)還比較簡(jiǎn)單,下面就是“processURL”方法實(shí)現(xiàn)此功能的代碼:

URLConnectionconnection=url.openConnection();

if((connection.getContentType()!=null)&&!connection.getContentType().toLowerCase().startsWith("text/")){

getWorkloadWaiting().remove(url);

getWorkloadProcessed().add(url);

log("Notprocessingbecausecontenttypeis:"+

connection.getContentType());

return;

}首先,為每個(gè)傳遞進(jìn)來(lái)的變量url中存儲(chǔ)的URL構(gòu)造一個(gè)“URLConnection”對(duì)象,因?yàn)榫W(wǎng)站上會(huì)有多種類(lèi)型的文檔,而“蜘蛛”只對(duì)那些包含HTML,尤其是基于文本的文檔感興趣。前述代碼是為了確保文檔內(nèi)容以“text/”打頭,如果文檔類(lèi)型為非文本,會(huì)從等待區(qū)移除此URL,并把它添加到已處理區(qū),這也是為了保證不會(huì)再次訪問(wèn)此URL。在對(duì)特定URL建立連接之后,接下來(lái)就要解析其內(nèi)容了。下面的代碼打開(kāi)了URL連接,并讀取內(nèi)容:InputStreamis=connection.getInputStream();Readerr=newInputStreamReader(is);現(xiàn)在,我們有了一個(gè)Reader對(duì)象,可以用它來(lái)讀取此URL的內(nèi)容,對(duì)本文中的“蜘蛛”來(lái)說(shuō),只需簡(jiǎn)單地把其內(nèi)容傳遞給HTML解析器就可以了。本例中使用的HTML解析器為SwingHTML解析器,其由Java內(nèi)置,但由于Java對(duì)HTML解析的支持力度不夠,所以必須重載一個(gè)類(lèi)來(lái)實(shí)現(xiàn)對(duì)HTML解析器的訪問(wèn),這就是為什么我們要調(diào)用“HTMLEditorKit”類(lèi)中的“getParser”方法。但不幸的是,Sun公司把這個(gè)方法置為protected,唯一的解決辦法就是創(chuàng)建自己的類(lèi)并重載“getParser”方法,并把它置為public,這由“HTMLParse”類(lèi)來(lái)實(shí)現(xiàn),請(qǐng)看例4:importjavax.swing.text.html.*;publicclassHTMLParseextendsHTMLEditorKit{publicHTMLEditorKit.ParsergetParser(){returnsuper.getParser();}}這個(gè)類(lèi)用在Spider類(lèi)的“processURL”方法中,我們也會(huì)看到,Reader對(duì)象會(huì)用于讀取傳遞到“HTMLEditorKit.Parser”中網(wǎng)頁(yè)的內(nèi)容:HTMLEditorKit.Parserparse=newHTMLParse().getParser();parse.parse(r,newParser(url),true);請(qǐng)留意,這里又構(gòu)造了一個(gè)新的Parser類(lèi),這個(gè)Parser類(lèi)是一個(gè)Spider類(lèi)中的內(nèi)嵌類(lèi),而且還是一個(gè)回調(diào)類(lèi),它包含了對(duì)應(yīng)于每種HTMLtag將要調(diào)用的特定方法。在本文中,我們只需關(guān)心兩類(lèi)回調(diào)函數(shù),它們分別對(duì)應(yīng)一個(gè)簡(jiǎn)單tag(即不帶結(jié)束tag的tag,如)和一個(gè)開(kāi)始tag,這兩類(lèi)回調(diào)函數(shù)名為“handleSimpleTag”和“handleStartTag”。因?yàn)槊糠N的處理過(guò)程都是一樣的,所以“handleStartTag”方法僅是簡(jiǎn)單地調(diào)用“handleSimpleTag”,而“handleSimpleTag”則會(huì)負(fù)責(zé)從文檔中取出超鏈接,這些超鏈接將會(huì)用于定位“蜘蛛”要訪問(wèn)的其他頁(yè)面。在當(dāng)前tag被解析時(shí),“handleSimpleTag”會(huì)檢查是否存在一個(gè)“href”或超文本引用:Stringhref=(String)a.getAttribute(HTML.Attribute.HREF);if((href==null)&&(t==HTML.Tag.FRAME))href=(String)a.getAttribute(HTML.Attribute.SRC);if(href==null)return;如果不存在“href”屬性,會(huì)繼續(xù)檢查當(dāng)前tag是否為一個(gè)Frame,F(xiàn)rame會(huì)使用一個(gè)“src”屬性指向其他頁(yè)面,一個(gè)典型的超鏈接通常為以下形式:上面鏈接中的“href”屬性指向其鏈接到的頁(yè)面,但是“l(fā)inkedpage.html”不是一個(gè)地址,它只是指定了這個(gè)Web服務(wù)器上一個(gè)頁(yè)面上的某處,這稱(chēng)為相對(duì)URL,相對(duì)URL必須被解析為絕對(duì)URL,而這由以下代碼完成:URLurl=newURL(base,str);這又會(huì)構(gòu)造一個(gè)URL,str為相對(duì)URL,base為這個(gè)URL上的頁(yè)面,這種形式的URL類(lèi)構(gòu)造函數(shù)可構(gòu)造一個(gè)絕對(duì)URL。在URL變?yōu)檎_的絕對(duì)形式之后,通過(guò)檢查它是否在等待區(qū),來(lái)確認(rèn)此URL是否已經(jīng)被處理過(guò)。如果此URL沒(méi)有被處理過(guò),它會(huì)添加到等待區(qū),之后,它會(huì)像其他URL一樣被處理。相關(guān)的代碼如下所示:1.CheckLinks.javaimportjava.awt.*;

importjavax.swing.*;

import.*;

importjava.io.*;

publicclassCheckLinksextendsjavax.swing.JFrameimplements

Runnable,ISpiderReportable{

/**

*Theconstructor.Performsetuphere.

*/

publicCheckLinks()

{

//{{INIT_CONTROLS

setTitle("FindBrokenLinks");

getContentPane().setLayout(null);

setSize(405,288);

setVisible(true);

label1.setText("EnteraURL:");

getContentPane().add(label1);

label1.setBounds(12,12,84,12);

begin.setText("Begin");

begin.setActionCommand("Begin");

getContentPane().add(begin);

begin.setBounds(12,36,84,24);

getContentPane().add(url);

url.setBounds(108,36,288,24);

errorScroll.setAutoscrolls(true);

errorScroll.setHorizontalScrollBarPolicy(javax.swing.

ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

errorScroll.setVerticalScrollBarPolicy(javax.swing.

ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

errorScroll.setOpaque(true);

getContentPane().add(errorScroll);

errorScroll.setBounds(12,120,384,156);

errors.setEditable(false);

errorScroll.getViewport().add(errors);

errors.setBounds(0,0,366,138);

current.setText("CurrentlyProcessing:");

getContentPane().add(current);

current.setBounds(12,72,384,12);

goodLinksLabel.setText("GoodLinks:0");

getContentPane().add(goodLinksLabel);

goodLinksLabel.setBounds(12,96,192,12);

badLinksLabel.setText("BadLinks:0");

getContentPane().add(badLinksLabel);

badLinksLabel.setBounds(216,96,96,12);

//}}

//{{INIT_MENUS

//}}

//{{REGISTER_LISTENERS

SymActionlSymAction=newSymAction();

begin.addActionListener(lSymAction);

//}}

}

/**

*Mainmethodfortheapplication

*

*@paramargsNotused

*/

staticpublicvoidmain(Stringargs[])

{

(newCheckLinks()).setVisible(true);

}

/**

*Addnotifications.

*/

publicvoidaddNotify()

{

//Recordthesizeofthewindowpriortocallingparent's

//addNotify.

Dimensionsize=getSize();super.addNotify();

if(frameSizeAdjusted)

return;

frameSizeAdjusted=true;//Adjustsizeofframeaccordingtotheinsetsandmenubar

Insetsinsets=getInsets();

javax.swing.JMenuBarmenuBar=getRootPane().getJMenuBar();

intmenuBarHeight=0;

if(menuBar!=null)

menuBarHeight=menuBar.getPreferredSize().height;

setSize(insets.left+insets.right+size.width,insets.top+

insets.bottom+size.height+

menuBarHeight);

}

//UsedbyaddNotify

booleanframeSizeAdjusted=false;

//{{DECLARE_CONTROLS

javax.swing.JLabellabel1=newjavax.swing.JLabel();

/**

*Thebeginorcancelbutton

*/

javax.swing.JButtonbegin=newjavax.swing.JButton();

/**

*TheURLbeingprocessed

*/

javax.swing.JTextFieldurl=newjavax.swing.JTextField();

/**

*Scrolltheerrors.

*/

javax.swing.JScrollPaneerrorScroll=

newjavax.swing.JScrollPane();

/**

*Aplacetostoretheerrorscreated

*/

javax.swing.JTextAreaerrors=newjavax.swing.JTextArea();

javax.swing.JLabelcurrent=newjavax.swing.JLabel();

javax.swing.JLabelgoodLinksLabel=newjavax.swing.JLabel();

javax.swing.JLabelbadLinksLabel=newjavax.swing.JLabel();

//}}

//{{DECLARE_MENUS

//}}

/**

*Thebackgroundspiderthread

*/

protectedThreadbackgroundThread;

/**

*Thespiderobjectbeingused

*/

protectedSpiderspider;

/**

*TheURLthatthespiderbeganwith

*/

protectedURLbase;

/**

*Howmanybadlinkshavebeenfound

*/

protectedintbadLinksCount=0;

/**

*Howmanygoodlinkshavebeenfound

*/

protectedintgoodLinksCount=0;

/**

*Internalclassusedtodispatchevents

*

*@author

wuhailin

*@version1.0

*/

classSymActionimplementsjava.awt.event.ActionListener{

publicvoidactionPerformed(java.awt.event.ActionEventevent)

{

Objectobject=event.getSource();

if(object==begin)

begin_actionPerformed(event);

}

}

/**

*Calledwhenthebeginorcancelbuttonsareclicked

*

*@parameventTheeventassociatedwiththebutton.

*/

voidbegin_actionPerformed(java.awt.event.ActionEventevent)

{

if(backgroundThread==null){

begin.setLabel("Cancel");

backgroundThread=newThread(this);

backgroundThread.start();

goodLinksCount=0;

badLinksCount=0;

}else{

spider.cancel();

}

}

/**

*Performthebackgroundthreadoperation.Thismethod

*actuallystartsthebackgroundthread.

*/

publicvoidrun()

{

try{

errors.setText("");

spider=newSpider(this);

spider.clear();

base=newURL(url.getText());

spider.addURL(base);

spider.begin();

RunnabledoLater=newRunnable()

{

publicvoidrun()

{

begin.setText("Begin");

}

};

SwingUtilities.invokeLater(doLater);

backgroundThread=null;

}catch(MalformedURLExceptione){

UpdateErrorserr=newUpdateErrors();

err.msg="Badaddress.";

SwingUtilities.invokeLater(err);

}

}

/**

*CalledbythespiderwhenaURLisfound.Itishere

*thatlinksarevalidated.

*

*@parambaseThepagethatthelinkwasfoundon.

*@paramurlTheactuallinkaddress.

*/

publicbooleanspiderFoundURL(URLbase,URLurl)

{

UpdateCurrentStatscs=newUpdateCurrentStats();

cs.msg=url.toString();

SwingUtilities.invokeLater(cs);

if(!checkLink(url)){

UpdateErrorserr=newUpdateErrors();

err.msg=url+"(onpage"+base+")\n";

SwingUtilities.invokeLater(err);

badLinksCount++;

returnfalse;

}

goodLinksCount++;

if(!url.getHost().equalsIgnoreCase(base.getHost()))

returnfalse;

else

returntrue;

}

/**

*CalledwhenaURLerrorisfound

*

*@paramurlTheURLthatresultedinanerror.

*/

publicvoidspiderURLError(URLurl)

{

}

/**

*Calledinternallytocheckwhetheralinkisgood

*

*@paramurlThelinkthatisbeingchecked.

*@returnTrueifthelinkwasgood,falseotherwise.

*/

protectedbooleancheckLink(URLurl)

{

try{

URLConnectionconnection=url.openConnection();

connection.connect();

returntrue;

}catch(IOExceptione){

returnfalse;

}

}

/**

*Calledwhenthespiderfindsane-mailaddress

*

*@paramemailTheemailaddressthespiderfound.

*/

publicvoidspiderFoundEMail(Stringemail)

{

}

/**

*Internalclassusedtoupdatetheerrorinformation

*inaThread-Safeway

*/classUpdateErrorsimplementsRunnable{

publicStringmsg;

publicvoidrun()

{

errors.append(msg);

}

}

/**

*Usedtoupdatethecurrentstatusinformation

*ina"Thread-Safe"way

*/

classUpdateCurrentStatsimplementsRunnable{

publicStringmsg;

publicvoidrun()

{

current.setText("CurrentlyProcessing:"+msg);

goodLinksLabel.setText("GoodLinks:"+goodLinksCount);

badLinksLabel.setText("BadLinks:"+badLinksCount);

}

}

}2.ISpiderReportable.javaimport.*;interfaceISpiderReportable{

publicbooleanspiderFoundURL(URLbase,URLurl);

publicvoidspiderURLError(URLurl);

publicvoidspiderFoundEMail(Stringemail);

}3.Spider.javaimportjava.util.*;

import.*;

importjava.io.*;

importjavax.swing.text.*;

importjavax.swing.text.html.*;/**

*Thatclassimplementsareusablespider

*/

publicclassSpider{

/**

*AcollectionofURLsthatresultedinanerror

*/

protectedCollectionworkloadError=newArrayList(3);

/**

*AcollectionofURLsthatarewaitingtobeprocessed

*/

protectedCollectionworkloadWaiting=newArrayList(3);

/**

*AcollectionofURLsthatwereprocessed

*/

protectedCollectionworkloadProcessed=newArrayList(3);

/**

*TheclassthatthespidershouldreportitsURLsto

*/

protectedISpiderReportablereport;

/**

*Aflagthatindicateswhetherthisprocess

*shouldbecanceled

*/

protectedbooleancancel=false;

/**

*Theconstructor

*

*@paramreportAclassthatimplementstheISpiderReportable

*interface,thatwillreceiveinformationthatthe

*spiderfinds.

*/

publicSpider(ISpiderReportablereport)

{

this.report=report;

}

/**

*GettheURLsthatresultedinanerror.

*

*@returnAcollectionofURL's.

*/

publicCollectiongetWorkloadError()

{

returnworkloadError;

}

/**

*GettheURLsthatwerewaitingtobeprocessed.

*YoushouldaddoneURLtothiscollectionto

*beginthespider.

*

*@returnAcollectionofURLs.

*/

publicCollectiongetWorkloadWaiting()

{

returnworkloadWaiting;

}

/**

*GettheURLsthatwereprocessedbythisspider.

*

*@returnAcollectionofURLs.

*/

publicCollectiongetWorkloadProcessed()

{

returnworkloadProcessed;

}

/**

*Clearalloftheworkloads.

*/

publicvoidclear()

{

getWorkloadError().clear();

getWorkloadWaiting().clear();

getWorkloadProcessed().clear();

}

/**

*Setaflagthatwillcausethebegin

*methodtoreturnbeforeitisdone.

*/

publicvoidcancel()

{

cancel=true;

}

/**

*AddaURLforprocessing.

*

*@paramurl

*/

publicvoidaddURL(URLurl)

{

if(getWorkloadWaiting().contains(url))

return;

if(getWorkloadError().contains(url))

return;

if(getWorkloadProcessed().contains(url))

return;

log("Addingtoworkload:"+url);

getWorkloadWaiting().add(url);

}

/**

*CalledinternallytoprocessaURL

*

*@paramurlTheURLtobeprocessed.

*/

publicvoidprocessURL(URLurl)

{

try{

log("Processing:"+url);

//gettheURL'scontents

URLConnectionconnection=url.openConnection();

if((connection.getContentType()!=null)&&

!connection.getContentType().toLowerCase().startsWith("text/")){

getWorkloadWaiting().remove(url);

getWorkloadProcessed().add(url);

log("Notprocessingbecausecontenttypeis:"+

connection.getContentType());

return;

}

//readtheURL

InputStreamis=connection.getInputStream();

Readerr=newInputStreamReader(is);

//parsetheURL

HTMLEditorKit.Parserparse=newHTMLParse().getParser();

parse.parse(r,newParser(url),true);

}catch(IOExceptione){

getWorkloadWaiting().remove(url);

getWorkloadError().add(url);

log("Error:"+url);

report.spiderURLError(url);

return;

}

//markURLascomplete

getWorkloadWaiting().remove(url);

getWorkloadProcessed().add(url);

log("Complete:"+url);

}

/**

*Calledtostartthespider

*/

publicvoidbegin()

{

cancel=false;

while(!getWorkloadWaiting().isEmpty()&&!cancel){

Objectlist[]=getWorkloadWaiting().toArray();

for(int

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論