基于广度优先算法的多线程爬虫程序毕业设计.docx

上传人:b****8 文档编号:29168790 上传时间:2023-07-21 格式:DOCX 页数:71 大小:810.10KB
下载 相关 举报
基于广度优先算法的多线程爬虫程序毕业设计.docx_第1页
第1页 / 共71页
基于广度优先算法的多线程爬虫程序毕业设计.docx_第2页
第2页 / 共71页
基于广度优先算法的多线程爬虫程序毕业设计.docx_第3页
第3页 / 共71页
基于广度优先算法的多线程爬虫程序毕业设计.docx_第4页
第4页 / 共71页
基于广度优先算法的多线程爬虫程序毕业设计.docx_第5页
第5页 / 共71页
点击查看更多>>
下载资源
资源描述

基于广度优先算法的多线程爬虫程序毕业设计.docx

《基于广度优先算法的多线程爬虫程序毕业设计.docx》由会员分享,可在线阅读,更多相关《基于广度优先算法的多线程爬虫程序毕业设计.docx(71页珍藏版)》请在冰豆网上搜索。

基于广度优先算法的多线程爬虫程序毕业设计.docx

基于广度优先算法的多线程爬虫程序毕业设计

基于广度优先算法的多线程爬虫程序毕业设计

1绪论

1.1网络爬虫的发展

在互联网发展的早期,网站数量相对较少,信息数据量不大,查找也比较容易。

然而伴随互联网井喷性的发展,普通网络用户想找到自己所需的数据简直如同在数据的海洋里捞针,为满足大众信息检索需求的专业搜索网站便应运而生了。

所有搜索引擎的鼻祖,是1990年由Montreal的McGillUniversity三名学生(AlanEmtage、PeterDeutsch、BillWheelan)发明的Archie(ArchieFAQ)。

AlanEmtage等想到了开发一个可以用文件名查找文件的系统,于是便有了Archie。

Archie是第一个自动索引互联网上匿名FTP网站文件的程序,但它还不是真正的搜索引擎。

Archie是一个可搜索的FTP文件名列表,用户必须输入精确的文件名搜索,然后Archie会告诉用户哪一个FTP地址可以下载该文件。

由于Archie深受欢迎,受其启发,NevadaSystemComputingServices大学于1993年开发了一个Gopher(GopherFAQ)搜索工具Veronica(VeronicaFAQ)。

Jughead是后来另一个Gopher搜索工具。

虽然当时万维网还未出现,但网络中档传输还是相当频繁的,而且由于大量的档散布在各个分散的FTP主机中,查询起来非常不便,因此AlanArchie工作原理与现在的搜索引擎已经很接近,它依靠脚本程序自动搜索网上的文件,然后对有关信息进行索引,供使用者以一定的表达式查询。

当时,“机器人”一词在编程者中十分流行。

计算机“机器人”(ComputerRobot)是指某个能以人类无法达到的速度不间断地执行某项任务的软件程序。

由于专门用于检索信息的“机器人”程序象蜘蛛一样在网络间爬来爬去,因此,搜索引擎的“机器人”程序就被称为“蜘蛛”程序。

世界上第一个用于监测互联网发展规模的“机器人”程序是MatthewGray开发的WorldwideWebWanderer。

刚开始它只用来统计互联网上的服务器数量,后来则发展为能够检索网站域名。

与Wanderer相对应,MartinKosher于1993年10月创建了ALIWEB,它是Archie的HTTP版本。

ALIWEB不使用“机器人”程序,而是靠网站主动提交信息来建立自己的链接索引,类似于现在我们熟知的Yahoo。

随着互联网的迅速发展,使得检索所有新出现的网页变得越来越困难,因此,在MatthewGray的Wanderer基础上,一些编程者将传统的“蜘蛛”程序工作原理作了些改进。

直到一些编程者提出了这样的设想,既然所有网页都可能有连向其它网站的链接,那么从跟踪一个网站的链接开始,就有可能检索整个互联网。

到1993年底,一些基于此原理的搜索引擎开始纷纷涌现,但是早期的搜索引擎只是以搜索工具在数据库中找到匹配信息的先后次序排列搜索结果,因此毫无信息关联度可言。

而RBSE是第一个在搜索结果排列中引入关键词串匹配程度概念的引擎。

最早现代意义上的搜索引擎出现于1994年7月。

当时MichaelMauldin将JohnLeavitt的蜘蛛程序接入到其索引程序中,创建了大家现在熟知的Lycos(2000年被西班牙网络集团TerraLycosNetwork收购)。

同年4月,斯坦福(Stanford)大学最为著名的两名博士生,美籍华人杨致远(GerryYang)和DavidFilo共同创办了Yahoo公司,并成功地使搜索引擎的概念深入人心。

从此搜索引擎进入了高速发展时期。

目前,互联网上有名有姓的搜索引擎已达数百家,其检索的信息量也与从前不可同日而语。

像国外的Google,国内的XX,这样的搜索引擎巨擘由于掌握的大多数的入口流量,成为互联网世界的霸主,并带来了巨大的商业价值。

1.2国内外技术发展现状

因为搜索引擎的商业化应用带来了巨大的商业价值,所以作为搜索引擎的核心部分的网络爬虫技术,也理所应当的成为了国内外研究的热点。

对于网络爬虫的研究从上世纪九十年代就开始了目前爬虫技术已经相当成熟。

并催生了像Baidu和Google这样的网络巨擘,而其它公司也纷纷推出了自己的搜索引擎。

网络爬虫是搜索引擎的重要组成部分。

现今,网络爬虫主要分为通用爬虫和聚焦爬虫两类。

通用搜索引擎的目标是尽可能大的网络覆盖率,通用搜索引擎大多提供基于关键词的检索。

聚焦爬虫是一个自动下载网页的程序,它根据既定的抓取目标,有选择的访问万维网上的网页与相关的链接,获取所需要的信息。

与通用爬虫(generalpurposewebcrawler)不同,聚焦爬虫并不追求大的覆盖,而将目标定为抓取与某一特定主题内容相关的网页,为面向主题的用户查询准备数据资源。

同时,支持根据语义信息提出的查询。

网络爬虫的发展趋势随着AJAX/Web2.0等技术的流行,如何抓取AJAX等动态页面成了搜索引擎急需解决的问题,如果搜索引擎依旧采用“爬”的机制,是无法抓取到AJAX页面的有效数据的。

除此之外,网络爬虫还主要面对着一下的这些问题(摘自XX百科[5]):

1、强制用Cookies。

部分站长为了让用户记住登陆信息,强迫用户使用Cookies。

如果未开启,则无法进行访问,访问页面显示的也不会正常,这种方式会让蜘蛛无法进行访问。

2、登陆要求。

有些企业站和个人站的设置一定要注册登陆后才能看到相关的文章内容,这种对蜘蛛不是很友好,蜘蛛不会注册、也不会登陆。

3、动态URL。

动态URL简单的说就是带有问号、等号及参数的网址就是动态URL,动态URL不利于搜索引擎蜘蛛的爬行和抓取。

4、Flash。

有的网站页面使用Flash视觉效果是很正常的,比如用Flash做的Logo、广告、图表等,这些对搜索引擎抓取和收录是没有问题的,很多网站的首页是一个大的Flash档,这种就叫蜘蛛陷阱,在蜘蛛抓取时HTML代码中只是一个链接,并没有文字。

虽然大的Flash效果看上去很好,外观看着也很漂亮,但可惜搜索引擎看不到,无法读取任何内容。

5、无休止的跳转。

对搜索引擎来说只对301跳转相对来说比较友好,对其他形式的跳转都是比较敏感,例如:

JavaScript跳转、MetaRefresh跳转、Flash跳转、302跳转。

1.3系统设计的意义

本文通过JAVA语言实现一个基于广度优先偏历算法的多线程爬虫程序。

通过实现此爬虫程序可以定点搜集某一站点的URLs,如果需要搜集其它信息,可以在解析URLs的同时,解析获取相应信息

 

2总体设计方案

2.1系统设计方案

本设计主要是通过在eclipse软件环境中进行,设计过程中首先服务器端获得网页URL,URL的获得途径有从客户端获得的已经形成的URL,和解析网站获得的更新的URL两种途径,然后根据URL连接该网页,获取网页源代码,获取网页源代码中需要的网页内容,去除多余的标签,空格,最后形成XML文档,服务器端的还包含获得IP代理,因为反复解析同一个网站,网站的防火墙会让本地IP无法访问该网站,所以我们需要用到IP代理循环访问网站解决这个问题,服务器端还可以阅本地文件的模块,方便文件阅读的客户端主要是过滤本地的文档与服务器端进行信息交互,传送需要解析的URL,获得已经解析的网页源代码所形成的XML文档。

2.2系统设计框图

是否

 

图2.1.1网页解析部分流程图

 

 

图2.1.2客户端文件遍历流程图图2.1.3服务器端与客户端通信流程图

2.3网络爬虫的相关技术

2.3.1URL

统一资源定位符(URL,英语UniformResourceLocator的缩写)也被称为网页地址,是因特网上标准的资源的地址。

它最初是由蒂姆·伯纳斯-李发明用来作为万维网的地址的。

现在它已经被万维网联盟编制为因特网标准RFC1738了。

在因特网的历史上,统一资源定位符的发明是一个非常基础的步骤。

统一资源定位符的语法是一般的,可扩展的,它使用ASCII代码的一部分来表示因特网的地址。

一般统一资源定位符的开始标志着一个计算机网络所使用的网络协议。

统一资源定位符是统一资源标志符的一个下种。

统一资源标志符确定一个资源,而统一资源定位符不但确定一个资源,而且还表示出它在哪里。

URL结构一般分为两个部分,一个是物理结构,一个是逻辑结构。

在物理结构包括扁平结构和树型结构。

扁平结构就是网站中所有的页面都是在根目录这一级别,形成一个扁平的物理结构。

这比较适合于小型的网站,因为如果太多文件都放在根目录下的话,制作和维护起来比较麻烦。

而树型结构的意义是在一级目录下分为多个频道或者称之为目录,然后目录下面再放上属于这个频道的页面,首页、频道首页、频道下的内容就好比树干、树枝、树叶的关系。

逻辑结构就是由网页内部链接所形成的逻辑的或链接的网络图。

比较好的情况是逻辑结构与前面的树型物理结构相吻合。

统一资源定位符URL是对可以从因特网上得到的资源的位置和访问方法的一种简洁的表示。

URL给资源的位置提供一种抽象的识别方法,并用这种方法给资源定位。

只要能够对资源定位,系统就可以对资源进行各种操作,如存取、更新、替换和查找其属性。

URL相当于一个文件名在网络范围的扩展。

因此URL是与因特网相连的机器上的任何可访问对象的一个指针。

URL的一般形式是:

:

//<主机>:

<端口>/<路径>

网络爬虫就是通过提取和分析出网页中的URL地址,对相应网络进行爬取。

2.3.2HTTP协议

超文本传输协议(HTTP-Hypertexttransferprotocol)是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文文件的数据传送协议。

2.3.2.1HTTP协议简介

超文本传输协议(HTTP-Hypertexttransferprotocol)是分布式,协作式,超媒体系统应用之间的通信协议。

是万维网(worldwideweb)交换信息的基础。

HTTP是IETF(InternetEngineeringTaskForce)制定的国际化标准。

在HTTP标准制定和实现的过程中,W3C积极参与了其中的工作,并发挥了重要作用。

它允许将超文本标记语言(HTML)文档从Web服务器传送到Web浏览器。

HTML是一种用于创建文文件的标记语言,这些文文件包含到相关信息的链接。

您可以单击一个链接来访问其它文文件、图像或多媒体对象,并获得关于链接项的附加信息。

HTTP协议的主要特点可概括如下:

1、简单快速:

客户向服务器请求服务时,只需传送请求方法和路径。

请求方法常用的有GET、HEAD、POST。

每种方法规定了客户与服务器联系的类型不同。

由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

2、灵活:

HTTP允许传输任意类型的数据对象。

正在传输的类型由Content-Type加以标记。

3、无连接:

无连接的含义是限制每次连接只处理一个请求。

服务器处理完客户的请求,并收到客户的应答后,即断开连接。

采用这种方式可以节省传输时间。

4、无状态:

HTTP协议是无状态协议。

无状态是指协议对于事务处理没有记忆能力。

缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。

另一方面,在服务器不需要先前信息时它的应答就较快。

2.3.2.2HTTP消息结构

Request消息结构:

Response消息结构:

2.3.2.3请求方法

根据HTTP标准,HTTP请求可以使用多种请求方法。

例如:

HTTP1.1目前支持7种请求方法:

GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。

GET请求获取由Request-URI所标识的资源。

POST在Request-URI所标识的资源后附加新的数据。

HEAD请求获取由Request-URI所标识的资源的响应消息报头。

OPTIONS请求查询服务器的性能,或查询与资源相关的选项和需求。

PUT请求服务器存储一个资源,并用Request-URI作为其标识。

DELETE请求服务器删除由Request-URI所标识的资源。

TRACE请求服务器回送收到的请求信息,主要用语测试或诊断。

URI完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。

一个URL地址用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。

其中最常见的就是GET和POST了。

GET一般用于获取/查询资源信息;而POST一般用于更新资源信息。

以下是二者的区别:

1.GET提交的数据会放在URL之后,以?

分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?

name=test1&id=123456;POST方法是把提交的数据放在HTTP包的Body中;

2.GET提交的数据大小有限制(因为浏览器对URL的长度有限制?

也有人说依服务器的处理能力而定);而POST方法提交的数据没有限制;

3.GET方式需要使用Request.QueryString来取得变量的值;而POST方式通过Request.Form来获取变数的值;

4.GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其它人可以访问这台机器,就可以从历史记录获得该用户的账号和密码;

2.3.2.4HTTP状态代码

状态代码由3位数字组成,表示请求是否被理解或被满足。

状态描述:

状态描述给出了关于状态代码的简短的文字描述。

状态代码的第一个数字定义了响应的类别,后面两位没有具体的分类。

第一个数字有五种可能的取值:

-1xx:

指示信息—表示请求已接收,继续处理。

-2xx:

成功—表示请求已经被成功接收、理解、接受。

-3xx:

复位向—要完成请求必须进行更进一步的操作。

-4xx:

客户端错误—请求有语法错误或请求无法实现。

-5xx:

服务器端错误—服务器未能实现合法的请求。

状态代码状态描述说明

200OK客户端请求成功

400BadRequest由于客户端请求有语法错误,不能被服务器所理解。

401Unauthonzed请求XX。

这个状态代码必须和WWW-Authenticate报头域一起使用

403Forbidden服务器收到请求,但是拒绝提供服务。

服务器通常会在回应正文中给出不提供服务的原因

404NotFound请求的资源不存在,例如,输入了错误的URL。

500InternalServerError服务器发生不可预期的错误,导致无法完成客户端的请求。

503ServiceUnavailable服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。

2.3.3JAVA多线程

在一个程序中,一些独立运行的程序片断叫做“线程”(Thread),利用它编程的概念就叫作“多线程处理”。

(摘自XX百科[5])

2.3.3.1定义

线程的概念来源于计算机的操作系统的进程的概念。

进程是一个程序关于某个数据集的一次运行。

也就是说,进程是运行中的程序,是程序的一次运行活动。

线程和进程的相似之处在于,线程和运行的程序都是单个顺序控制流。

有些教材将线程称为轻量级进程(lightweightprocess)。

线程被看作是轻量级进程是因为它运行在一个程序的上下文内,并利用分配给程序的资源和环境。

作为单个顺序控制流,线程必须在运行的程序中得到自己运行的资源,如必须有自己的执行栈和程序计数器。

线程内运行的代码只能在该上下文内。

因此还有些教程将执行上下文(executioncontext)作为线程的同义词。

所有的程序员都熟悉顺序程序的编写,如我们编写的名称排序和求素数的程序就是顺序程序。

顺序程序都有开始、执行序列和结束,在程序执行的任何时刻,只有一个执行点。

线程(thread)则是进程中的一个单个的顺序控制流。

单线程的概念很简单,如图所示。

多线程(multi-thread)是指在单个的程序内可以同时运行多个不同的线程完成不同的任务,图2.3.3.1.2说明了一个程序中同时有两个线程运行。

一个线程

两个线程

图2.3.3.1.1单线程程序示意图图2.3.3.1.2多线程程序示意图

有些程序中需要多个控制流并行执行。

例如,

for(inti=0;i<100;i++)

System.out.println("RunnerA="+i);

for(intj=0;j<100;j++)

System.out.println("RunnerB="+j);

上面的代码段中,在只支持单线程的语言中,前一个循环不执行完不可能执行第二个循环。

要使两个循环同时执行,需要编写多线程的程序。

很多应用程序是用多线程实现的,如HotJavaWeb浏览器就是多线程应用的例子。

在HotJava浏览器中,你可以一边滚动屏幕,一边下载Applet或图像,可以同时播放动画和声音等。

2.3.3.2优点

使用线程可以把占据时间长的程序中的任务放到后台去处理。

用户接口可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。

程序的运行速度可能加快。

在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。

在这种情况下可以释放一些珍贵的资源如内存占用等等。

还有其它很多使用多线程的好处,这里就不在累述。

2.3.3.3不足

1.如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换。

2.更多的线程需要更多的内存空间。

3.线程可能会给程序带来更多“Bug”,因此要小心使用。

4.线程的中止需要考虑其对程序运行的影响。

5.通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生。

2.3.3.4JAVA多线程编程

计算机程序得以执行的三个要素是:

CPU,程序代码,可存取的数据。

在JAVA语言中,多线程的机制是通过虚拟CPU来实现的。

可以形象的理解为,在一个JAVA程序内部虚拟了多台计算机,每台计算机对应一个线程,有自己的CPU,可以获取所需的代码和数据,因此能独立执行任务,相互间还可以共享代码和数据。

JAVA的线程是通过java.lang.Thread类来实现的,它内部实现了虚拟CPU的功能,能够接收和处理传递给它的代码和资料,并提供了独立的运行控制功能。

每个JAVA应用程序都至少有一个线程,这就是所谓的主线程。

它由JVM创建并调用JAVA应用程序的main方法。

Java语言实现多线程编程的类和接口。

在java.lang包中定义了Runnable接口和Thread类。

Runnable界面中只定义了一个方法,它的格式为:

publicabstractvoidrun()

这个方法要由实现了Runnable接口的类实现。

Runnable对象称为可运行对象,一个线程的运行就是执行该对象的run()方法。

Thread类实现了Runnable接口,因此Thread对象也是可运行对象。

同时Thread类也是线程类,该类的构造方法如下:

publicThread()

publicThread(Runnabletarget)

publicThread(Stringname)

publicThread(Runnabletarget,Stringname)

publicThread(ThreadGroupgroup,Runnabletarget)

publicThread(ThreadGroupgroup,Stringname)

publicThread(ThreadGroupgroup,Runnabletarget,Stringname)

target为线程运行的目标对象,即线程调用start()方法启动后运行那个对象的run()方法,该对象的类型为Runnable,若没有指定目标对象,则以当前类对象为目标对象;name为线程名,group指定线程属于哪个线程组。

Thread类的常用方法有:

publicstaticThreadcurrentThread()返回当前正在执行的线程对象的引用。

publicvoidsetName(Stringname)设置线程名。

publicStringgetName()返回线程名。

publicstaticvoidsleep(longmillis)throwsInterruptedException

publicstaticvoidsleep(longmillis,intnanos)throwsInterruptedException

使当前正在执行的线程暂时停止执行指定的毫秒时间。

指定时间过后,线程继续执行。

该方法抛出InterruptedException异常,必须捕获。

publicvoidrun()线程的线程体。

publicvoidstart()由JVM调用线程的run()方法,启动线程开始执行。

publicvoidsetDaemon(booleanon)设置线程为Daemon线程。

publicbooleanisDaemon()返回线程是否为Daemon线程。

publicstaticvoidyield()使当前执行的线程暂停执行,允许其它线程执行。

publicThreadGroupgetThreadGroup()返回该线程所属的线程组对象。

publicvoidinterrupt()中断当前线程。

publicbooleanisAlive()返回指定线程是否处于活动状态。

通常,我们可以将一个类继承Thread,然后,覆盖Thread中的run()方法,这样让这个类本身也就成了线程。

每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。

使用start()方法,线程进入Runnable状态,它将线程调度器注册这个线程。

调用start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入Runnble而不是Running。

我们也可以通过实现Runnable接口并实现接口中定义的唯一方法run(),可以创建一个线程。

在使用Runnable接口时,不能直接创建所需类的对象并运行它,而是必须从Thread类的一个实例内部运行它。

从上面两种创建线程的方法可以看出,如果继承Thread类,则这个类本身可以调用start方法,也就是说将这个继承了Thread的类当作目标对象;而如果实现Runnable接口,则这个类必须被当作其它线程的目标对象。

JAVA的线程从产生到消失,可分为5种状态:

新建(New),可运行(Runnable),运行(Running),阻塞(Blocked)以及死亡(Dead)。

其中,Running状态并非属于JAVA规范中定义的线程状态,也就是说,在JAV

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1