关键词不能为空

当前您在: 主页 > 英语 >

urk网络爬虫(Spider)Java实现原理

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-01-28 01:10
tags:

urk-小星星英语

2021年1月28日发(作者:accustom)



网络蜘蛛



或者说< /p>



网络爬虫




是一种能访问网站并跟踪链接的程序,


通过它,


可快速地画出一个网站所包含的网页地图信息。


本文主要讲述如何使用


Java


编程来构建一个





,我们会先以一个可复用的 蜘蛛类包装一个基本的



蜘蛛



,并在示例程序中演示如何创建一个特定的



蜘蛛



来扫描相关网站并找出死链接。



Java


语言在此非常适合构建一个



蜘蛛



程序,其内建了对


HTTP


协议的支持,通过它可以传输大部分的网页信息;其还内建了一个< /p>


HTML


解析器,正是这两个原因使


Ja va


语言成为本文构建



蜘蛛



程序的首选。



文章 后面例


1


的示例程序,将会扫描一个网站,并寻找死链接。使用 这个程序时需先输入一个


URL


并单击


“Begin”


按钮,程序开始之后,


“Begin”


按钮会变成


“Cancel”


按钮。

< p>
在程序扫描网站期间,会在


“Cancel”


按钮 之下显示进度,且在检查当前网页时,也会显示相关正常链接与死链接的数目,死链接将显示在程序底部的滚动文 本框中。单击


“Cancel”


按钮会停止扫描过程,


之后可以输入一个新的


URL



如果期间没有单击


“Cancel”



程序将会一直运行直到查找完所有网页,


此后,


“Ca ncel”


按钮会再次变回


“Begin”


表示程序已停止。



下面将


演示示例程序是如何与可复用


“Spider”

类交互


的,示例程序包含在例


1



CheckLinks


类中,


这个类实 现了


ISpiderReportable


接口,如例


2


所示,正是通过这个


接口,蜘蛛类才能与示例 程序相交互。在这个接口中,定义了三个方法:第一个方法是


“spiderFound URL”


,它在每次程序定位一个


URL


时被调用,如果方法返回


true


,表


示程序应继续执行下去并找出其中的链接;第二个方法是


“spiderURLErr or”


,它在每次程序检测


URL


导致 错误时被调用(如


“404


页面未找到



);第三个方法是


“spiderFoundEMail”


,它在每次发现电子邮件地址时被调用。有了这三个方法,


Sp ider


类就能把相关信息反馈给创建它的程序了。




begin


方法被调用后,

< br>“


蜘蛛



就开始工作了;为允许 程序重绘其用户界面,



蜘蛛



是作为一个单独的线程启动的。点击


“Begin”

< br>按钮会开始这个后台线程,当后台线程运行


之后,又会调用


“CheckLinks”


类的


run


方法,而


run


方法是由


Spide r


对象实例化时启动的,如下所示:



spider = new Spider(this);


();


base = new URL(t());


(base);


();


首先,


一个新的


Spider


对象被实例化< /p>



在此,


需要传递一个

< br>“


ISpiderReportable



对象给


Spider


对象的构造函数



因为


“CheckLinks”

类实现了



ISpiderReportable



接口,


只需简单地把它作为当前对象(可由关 键字


this


表示)传递给构造函数即可


;其次,


在程序中维护了一个其访问过的


URL


列表





clear



方法的调用则是为了确保程序开


始时


URL


列表为空,程序开始运行之前必须添 加一个


URL


到它的待处理列表中,此时用户输入的

< p>
URL


则是添加到列表中的第一个,程序就由扫描这个网页开始,并找到与


这个起始


URL


相链接的其他页面;最 后,调用


“begin”


方法开始运行



蜘蛛



,这个方法直到



蜘蛛



工作完毕或用户取 消才会返回。










蜘蛛



运行时,


可以调用由


“ISpiderReportable”


接口实现的三个方法来报告程序当前状态


,程序的大部分工作都是由


“spiderFoundURL”


方法


来 完成的,




蜘蛛


发现一个新的


URL


时,它首先 检查其是否有效,如果这个


URL


导致一个错误,就会把它当作 一个死链接;如果链接有效,就会继续检查它是否在一个不同的服务器上,如果


链接在同 一服务器上,


“spiderFoundURL”


返回


true



表示



蜘蛛



应继续跟踪这个

URL


并找出其他链接,


如果链接在另外的服务器上



就不会扫描是否还有其他链接,因为


这会导 致



蜘蛛



不 断地浏览


Internet


,寻找更多、更多的网站,所以,示 例程序只会查找用户指定网站上的链接。



构造


Spider




前面已经讲 了如何使用


Spider


类,请看例


3


中的代码。使用


Spider


类及


“ISpiderReportable”


接口能方便地为某一程序 添加



蜘蛛



功能,下面继续讲解


Spider


类是怎样

工作的。



Spider


类必须保 持对其访问过的


URL


的跟踪



这样做的目的是为了确保



蜘蛛



不会访问同一


URL


一次 以上


;进一步来说,



蜘蛛

< p>


必须把


URL


分成三组



第一组存储在


“workloadW aiting”


属性中,包含了一个未处理的


URL

< p>
列表,



蜘蛛



要访问的第一个


URL


也存在其中;第二组存储 在


“workloadProcessed”


中,它是



蜘蛛



已经处理过且


无需再次访问的


URL


;第三组存储在


“workloadError”


中,包含了发生错误的


URL




Begi n


方法包含了


Spider


类的主循环


,其一直重复遍历


“workloadWaiting”


,并处理其中的每一个页面,当然我们也想到了,在这些页面被处理时,很可能有其他的


URL


添加到


“workloadWaiti ng”


中,所以,


begin


方法一直 继续此过程,


直到调用


Spider


类 的


cancel


方法


,或



workloadWaiting”


中已不再剩有


URL


。这个过程如下:



cancel = false;


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


Object list[] =


getWorkloadW aiting


().toArray();


for ( int i=0; (i<)&&!cancel; i++=


processURL< /p>


((URL)list[i]);


}


当上述代码遍历


“workloadWaiting”


时,它 把每个需处理的


URL


都传递给



processURL



方法,

< p>
而这个方法才是真正读取并解析


URL



HTML


信息的




读取并解析


HTML


Java


同时支持访问


URL


内容及解析


HTML


,而这正是



pr ocessURL



方法要做的。在


J ava


中读取


URL


内容相对还比较简 单,下面就是


“processURL”


方法实现此功能的代< /p>


码:



URLConnection connection = nnection();


if ( (tentType()!=null) &&!tentType().toLowerCase().sta rtsWith(


getWorkloadWaiting().remove(url );


getWorkloadProcessed().add(url);


log(


tentType() );


return;


}


首先,


为每个传递进来的变量


url


中存储的


URL


构造一个



U RLConnection



对象


,< /p>


因为网站上会有多种类型的文档,



“< /p>


蜘蛛



只对那些包



HTML



尤其是基于文本的文档 感兴趣


。前述代码是为了确保文档内容以


“text/”


打头,如果文档类型为非文本,会从等待区移除此


URL




把它添加到已处理区,这也是为了保证不会再次 访问此


URL


。在对特定


URL


建立连接之后,接下来就要解析其内容了。下面的代码打开了


URL< /p>


连接,并读取内容:



InputStream is = utStream();


Reader r = new InputStreamReader(is);




//


字符流



reader



现在,我们有了一个< /p>


Reader


对象,可以用它来读取此


U RL


的内容,对本文中的



蜘蛛



来说,只需简单地把其内容传递给


HTML


解析器就


可以了。本例中使用的


HTM L


解析器为


Swing HTML


解析 器,其由


Java


内置,但由于


Jav a



HTML


解析的支持力度不够,所 以必须重载一


个类来实现对


HTML


解 析器的访问,这就是为什么我们要调用



HTMLEditor Kit



类中的


getParser



方法。但不幸的是,


Sun


公司把这个方法置



p rotected


,唯一的解决办法就是创建自己的类并重载


“ getParser”


方法,并把它置为


public


,这由



HTMLParse

< br>”


类来实现,请看例


4




import .*;


public



class


HTMLParse extends HTMLEditorKit {


public


getParser()


{


return ser();


}


}


这个类用在

< br>Spider


类的


“processURL”

< p>
方法中,我们也会看到,


Reader


对象会用于


读取


传递到


“”



网页的内容




























































//


这个地方意思是,所谓的回调方法,就是供别人调用的,当


parser


的对


reader

< p>
对象进行解析的时候,发现


标记


或者


文本


就会去调用


回调类


的方 法去执行相应的动作


reader



parse = new HTMLParse().getParser();


(


r


,new


Parser


(url),true);

请留意,


这里又构造了一个新的


Parser


类,


这个


Parser


类是 一个


Spider


类中的内嵌类,


而且 还是一个回调类,


它包含了对应于每种


HTML


tag


将要调用的特定方法。在本文中,我们只需关心两类回调函数,它们分 别对应


一个简单


tag


(即不带结束< /p>


tag



tag


,如)和


一个开始


tag


< p>
这两类回调函数名为



handleSimple Tag





handleStartTag



。因为每种的处理过程都是一 样的,所以



handleStartTag

< br>”


方法仅是简单地调




handleSimpleTag






handleSimpleTag



则会负责从文档中取出超链接


< p>
这些超链接将会用于定位



蜘蛛

< br>”


要访问的其他页面



在当前< /p>


tag


被解析时,


“handleSim pleTag”


会检查是否存在一个


“href”


或超文本引用:



String href = (String)ribute();


if( (href==null) && (t==) )


href = (String)ribute();


if ( href==null )


return;


如果不存在


“href”


属性,会继续检查 当前


tag


是否为一个


Frame



Frame


会使用一个

< br>“src”


属性指向其他页面,一个典型的超链接通常为


以下形式:



上面链接中的


“href ”


属性指向其链接到的页面,


但是


“”


不是一个地址,


它只是指定了这个


We b


服务器上一个页面上的某


处,这称为相对

URL



相对


URL


必须被解析为绝对


URL


,而这由以下代码完成:< /p>



URL url = new URL(base,str);


这又会构造一个


URL



str


为相对


URL



base


为这个


URL

上的页面,


这种形式的


URL


类构 造函数可构造一个绝对


URL


。在


UR L


变为正


确的绝对形式之后,


通过检查 它是否在等待区,来确认此


URL


是否已经被处理过

< p>


如果此


URL


没有被处 理过,它会添加到等待区,之后,它会


像其他


URL

< p>
一样被处理。



相关的代码如下所示:




import .*;



import .*;



import .*;



import .*;


public class CheckLinks extends implements



Runnable,ISpiderReportable {



/**



* The constructor. Perform setup here.



*/



public CheckLinks()



{



//{{INIT_CONTROLS



setTitle(



getContentPane().setLayout(null);



setSize(405,288);



setVisible(true);



t(



getContentPane().add(label1);



nds(12,12,84,12);



t(



ionCommand(



getContentPane().add(begin);



nds(12,36,84,24);



getContentPane().add(url);



nds(108,36,288,24);



oscrolls(true);



izontalScrollBarPolicy(.



NTAL_SCROLLBAR_ALWAYS);



ticalScrollBarPolicy(.



AL_SCROLLBAR_ALWAYS);



que(true);



getContentPane().add(errorScroll);



nds(12,120,384,156);



table(false);



wport().add(errors);



nds(0,0,366,138);



t(



getContentPane().add(current);



nds(12,72,384,12);



t(



getContentPane().add(goodLinksLabel);



nds(12,96,192,12);



t(



getContentPane().add(badLinksLabel);



nds(216,96,96,12);



//}}



//{{INIT_MENUS



//}}



//{{REGISTER_LISTENERS



SymAction lSymAction = new SymAction();



ionListener(lSymAction);



//}}



}



/**



* Main method for the application



*



* @param args Not used



*/



static public void main(String args[])



{



(new CheckLinks()).setVisible(true);



}



/**



* Add notifications.



*/



public void addNotify()



{



// Record the size of the window prior to calling parent's



// addNotify.



Dimension size = getSize();


ify();



if ( frameSizeAdjusted )



return;



frameSizeAdjusted = true;


// Adjust size of frame according to the insets and menu bar



Insets insets = getInsets();



ar menuBar = getRootPane().getJMenuBar();



int menuBarHeight = 0;



if ( menuBar != null )



menuBarHeight = ferredSize().height;



setSize( + + , +



+ +



menuBarHeight);



}



// Used by addNotify



boolean frameSizeAdjusted = false;



//{{DECLARE_CONTROLS



label1 = new ();



/**



* The begin or cancel button



*/



n begin = new n();



/**



* The URL being processed



*/



ield url = new ield();



/**



* Scroll the errors.



*/



lPane errorScroll =



new lPane();



/**



* A place to store the errors created



*/



rea errors = new rea();



current = new ();



goodLinksLabel = new ();



badLinksLabel = new ();



//}}



//{{DECLARE_MENUS



//}}



/**



* The background spider thread



*/



protected Thread backgroundThread;



/**



* The spider object being used



*/



protected Spider spider;



/**



* The URL that the spider began with



*/



protected URL base;



/**



* How many bad links have been found



*/



protected int badLinksCount = 0;



/**



* How many good links have been found



*/



protected int goodLinksCount = 0;




/**



* Internal class used to dispatch events



*



* @author wuhailin



* @version 1.0



*/



class SymAction implements Listener {



public void actionPerformed(Event event)



{



Object object = rce();



if ( object == begin )



begin_actionPerformed(event);



}



}



/**



* Called when the begin or cancel buttons are clicked



*



* @param event The event associated with the button.



*/



void begin_actionPerformed(Event event)



{



if ( backgroundThread==null ) {



el(



backgroundThread = new Thread(this);



();



goodLinksCount=0;



badLinksCount=0;



} else {



();



}



}



/**



* Perform the background thread operation. This method



* actually starts the background thread.



*/



public void run()



{



try {



t(



spider = new Spider(this);



();



base = new URL(t());



(base);



();



Runnable doLater = new Runnable()



{



public void run()



{



t(



}



};



Later(doLater);



backgroundThread=null;



} catch ( MalformedURLException e ) {



UpdateErrors err = new UpdateErrors();



=



Later(err);



}



}



/**



* Called by the spider when a URL is found. It is here



* that links are validated.



*



* @param base The page that the link was found on.



* @param url The actual link address.



*/



public boolean spiderFoundURL(URL base,URL url)



{



UpdateCurrentStats cs = new UpdateCurrentStats();



= ng();



Later(cs);



if ( !checkLink(url) ) {



UpdateErrors err = new UpdateErrors();



= url+



Later(err);



badLinksCount++;

urk-小星星英语


urk-小星星英语


urk-小星星英语


urk-小星星英语


urk-小星星英语


urk-小星星英语


urk-小星星英语


urk-小星星英语



本文更新与2021-01-28 01:10,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/575814.html

网络爬虫(Spider)Java实现原理的相关文章