分布式网络爬虫研究.docx
《分布式网络爬虫研究.docx》由会员分享,可在线阅读,更多相关《分布式网络爬虫研究.docx(28页珍藏版)》请在冰豆网上搜索。
分布式网络爬虫研究
淮北师范大学
2013届学士学位论文
分布式网络爬虫研究
学院计算机科学与技术学院
专业网络工程
研究方向分布式网络爬虫研究
学生姓名李邦柱
学号20091204026
指导教师姓名
指导教师职称
2013年5月16日
分布式网络爬虫研究
计算机科学与技术学院2013届毕业生李邦柱
指导教师:
xx
摘要:
网络爬虫(WebCrawler),通常简称爬虫,是搜索引擎的重要组成部分。
随着信息化的快速推进,作为搜索引擎不可或缺的一部分——网络爬虫,一直是个热门的研究话题,它的好坏,直接决定了搜索引擎的未来。
目前来看,网络爬虫的研究方向主要包括对网页搜索策略的研究和网页分析算法的研究两大方向,其中,网页搜索中的主题网络爬虫是个研究趋势,它根据一定的网页分析算法,过滤与主题无关的链接,保留符合条件的链接并放入待抓取队列。
本论文简要介绍了一种构建简单分布式网络爬虫模型的方法,并且提供了行之有效的理论分析和算法。
主要讨论了单个网络爬虫抓取网页的原理,以后扩展后的多爬虫分布式的模型方法。
在分布式的网络爬虫中主要介绍了其体系结构以及分布式网络爬虫模型中运用的算法与数据结构分析。
本文并没有涉及复杂的算法研究,只是通过学习和使用现有平台和技术,研究基于LinuxC++/C平台下的一个能够抓取同一域名下的、具有对URL有某个关键字限制下的部分网页的微型的网络爬虫,最后实现离线浏览功能。
从性质上来看,它更趋向与主题网络爬虫。
关键词:
网络爬虫;分布式网络爬虫;URL;哈希表;多线程;Linux
TheStudyofDistributedwebcrawler
SchoolofComputerScience&Technology2013Graduates
OfHuaibeiNormalUniversity
LiBang-Zhu
AnhuiHuaibei235000,China
SupervisedbyWangShuai,Instructor
Abstract:
Webcrawler,usuallyreferredtocrawler,isanimportantcomponentofsearchengine.Withtherapiddevelopmentofinformationtechnology,asanindispensablepartofsearchengine--webcrawler,hasbeenahotresearchtopic.wheatheritisgoodorbad,itdirectlydeterminesthefutureofsearchengines.Atpresent,theresearchofwebcrawlermainlyincludestwoaspects:
thestudyofwebsearchstrategyandwebanalysisalgorithms.Amongthem,themewebcrawlerinwebresearchisaresearchtrend,whichisbasedonacertainwebpageanalysisalgorithmandfiltersirrelevantlinks,retainqualifiedlinksandplaceintothecapturequeue.
Thispaperbrieflyintroducesamethodtobuildasimplemodelofdistributedwebcrawlerandprovidestheeffectivetheoreticalanalysisandthealgorithm.Itmainlydiscussestheprincipleofasinglewebcrawlerwebpageandthedistributedmethodofexpandedmultiplecrawlers.Inthedistributedwebcrawler,itmainlyintroducessystemstructure,theanalysisofalgorithmsanddatastructuresusedindistributedwebcrawlermodel.Thereisnocomplexalgorithmresearchinthisthesis.Throughlearningandusingtheexistingplatformandtechnology,theresearchandimplementationofaLinuxC/C++platformcancapturemicrocrawlerwhichisunderthesamedomainnameandhasakeywordrestrictionsofURLinmostwebpages,andfinallyrealizeofflinebrowsing.Fromthepointofnature,ittendstothemewebcrawler.
Keywords:
WebCrawler,Distributedwebcrawler,URL,LinuxSocket,multi-thread,Linux
目录
绪论5
一、网络爬虫的功能以及原理的概述6
1.1网页的搜索策略和网页的分析7
1.1.1网页搜索策略的选择7
1.2URL介绍7
1.3URL的标准化8
1.4网页抓取9
1.5网页分析10
1.6LinuxSocket通信13
1.6.1LinuxSocket简介13
1.6.2TCP/IP14
1.6.3客户端Socket函数介绍15
1.7Linux平台下单个爬虫程序运行及结果分析18
二、分布式网络爬虫模型结构的概述22
三、分布式网络爬虫中使用的主要算法与数据的分析24
3.1爬虫进程启动后的工作流程25
3.2判重服务进程启动后的主要工作流程26
3.2.1判重服务进程正常启动的主要过程26
3.2.2判重服务进程选举启动的主要过程26
3.2.3判重服务进程对某个爬虫进程异常退出后的处理过程27
四、结束语29
五、致谢30
参考文献31
绪论
大家常用的搜索引擎,例如Baidu,Google也都有自己的网络爬虫来帮他们抓取Internet海洋中的网页。
这里稍微插一段题外话,其实网络爬虫和网站维护经常都是对立的,因为有些爬虫刷新时间短,有些爬虫比较“笨”,会在网站里迷失了路等情况,引起给网站服务器发送大量请求,造成服务器压力过大而崩溃。
但话又说回来,一个设计良好的网络爬虫,再加上使用者良好的素质,是完全可以避免以上情况的。
总得来说,网络爬虫带来的好处远远大于它自身和使用者带来的坏处。
大家几乎每天都在直接或间接地享受网络爬虫带来的好处,那么一个普通的网络爬虫它到底是如何构成的,又是如何抓取网页的呢?
一、网络爬虫的功能以及原理的概述
网络爬虫是网络搜索引擎的主要部分,主要功能是在互联网中收集数据,是为信息检索功能提供可靠的数据支持。
一个网络爬虫算法的优劣以及效率的高低都将直接影响搜索引擎的众多性能指标,网络爬虫程序的最主要的功能就是在网络上对网页内容中超链接的提取与分析以及进行网页数据的抓取工作。
网络爬虫刚开始启动时,网络爬虫就会从一个可扩展的任务队列中得到一项任务,即待抓取的网页信息(比如标示该URL的文本信息以及URL),随后将该URL对应的网页文件下载到本地保存起来,并对其中的网页代码文本内容进行分析,提取其中的相关信息以及超链接,将提取的链接送入判重服务进程的队列中等待判重查询,然后将没有扩展过的URL和相关信息加入到任务队列中,等待后续扩展,以是单个爬虫使用的框架,看起来更像是主题爬虫的框架。
(见图1.1)。
图1.1
1.1网页的搜索策略和网页的分析
网络爬虫的搜索策略(爬虫的算法)的研究及其URL分析是目前研究的两大方向,一个成功的爬虫需要强大的搜索策略和快速的URL分析。
1.1.1网页搜索策略的选择
网络爬虫一般常用的网页搜索策略包括深度优先搜索、广度优先搜索、最佳优先搜索等。
深度优先搜索(DepthFirstSearch):
是指在抓取网页过程中,一直按一个方向搜索网页,直到碰到最底层,然后返回上一层,继续按原先的搜索策略搜索下去。
这种搜索策略在判定是否存在的问题上有些优势,但对于抓取网页来说,爬虫很容易陷入某个深渊,因为Internet网络本身就很复杂,再加上网页结构的复杂性,深度优先搜索策略几乎不被采用。
广度优先搜索(BreadthFirstSearch):
是指在抓取网页过程中,首先抓取第一层的网页,然后再抓取第二层的网页,依次类推……。
这种搜索策略使用一种叫队列的数据结构来完成,一旦找到新的URL,就把它加入到队列中;每次用队列最前面的URL来抓取网页。
但它也有自己的缺点,那就是随着层数的增加,大量无关的网页会被加进来。
最佳优先搜索(BestFirstSearch):
和它的名字一样,这种搜索策略使用某种算法,用来计算每个URL的优先度,并按照这个优先度从大到小排列在一个数组中,每次要抓取的网页即优先度最大URL的网页。
这种搜索策略的优点可以避免广度优先搜索大量的无关网页被加进来,其缺点就是容易陷入某个相关度小的区域而忽略更大的区域。
因此对它来说,设计一种好的算法很重要,或者结合其它的算法。
本文采用的是第二种算法,因为其简单易实现,又因为本文需要抓取的网页在同一个域名下,且有关键字约束,所以可以防止大量无关的网页流入。
1.2URL介绍
统一资源定位符(URL,英语UniformResourceLocator的缩写)也被称为网页地址,是因特网上标准的资源的地址。
它最初是由蒂姆•伯纳斯-李发明用来作为万维网的地址的。
现在它已经被万维网联盟编制为因特网标准RFC1738了。
由于爬虫是通过URL的定位来抓取网页的,因此,需要了解URL的基本格式,才能继续下一步工作。
URL相当于一个文件名在网络范围的扩展。
因此URL是与因特网相连的机器上的任何可访问对象的一个指针。
URL的一般形式是:
:
//<主机>:
<端口>/<路径>
URL的访问方式有:
1.ftp——文件传送协议FTP
2.http——超文本传送协议HTTP
3.News——USENET新闻
<主机>是存放资源的主机在因特网中的域名
URL地址格式排列为:
scheme:
//host:
port/path,
例如http:
//
1.3URL的标准化
看到这个标题,有人可能会想,URL本身就是标准的,还用得着你去标准化吗?
其实不然,在网页源代码中,有些是绝对路径,有些是相对路径,还有一些URL中存在字符‘#’,多个‘///’等等。
因此,需要对这些URL进行处理,分别得到每个URL的Host,Port,File。
以下是本文对URL的设定:
1.URL的File成员不能以‘/’结尾,若有则以‘\0’填充;若该File成员没有路径,则设定其路径为‘/’。
这样做的目的是为了便于URL排重。
2.URL的File成员中若有‘#’字符,则删除它及它以后的字符,剩余的字符串作为File的值。
3.若URL中没有显式表明端口,则默认Port成员的值为80。
若URL没有主机属性,则默认Host成员的值为初始URL的主机名
1.4网页抓取
在分析网页之前,首先网页需要被抓取下来,抓取的具体方法将会在后面介绍。
这里仅仅结合程序代码,分析一下数据从服务器保存到本地的过程。
第一部分:
分析之前,首先要明确的是:
当从sockfd读取数据时,最前面一部分是和网页本身无关的信息,比如有些网页未找到,就会返回404notfound等服务信息,类似的,每种情况会返回对应的信息,因此,对于一些服务信息,应该不予记录。
下面代码通过每次读取一个字节的内容,当读到‘>’字符时才开始正式记录网页内容。
while
(1){
n=read(sockfd,ch,1);
if(n<0){
if(errno==EAGAIN){
sleep
(1);
continue;
}
}
if(*ch=='>'){
headbuffer[j++]=*ch;
break;
}
}
headbuffer[j]=0;
第二部分:
定义一个tmp的字符数组,用来临时存放抓取的的网页,抓取方法与第一部分想同,都是用read函数,不同的是这里是一块一块抓取,效率上能比每次抓取一个字节要高。
为什么不直接存放到文件中,而要保存到临时数组中呢?
我的解释是:
因为下一步分析网页时,有个URL重定向的过程,程序还会继续修改tmp数组。
如果直接保存到文件,那么还得再次打开文件分析网页,这样会降低效率,因为在磁盘执行读写操作总是比在内存读写慢得多。
chartmp[MAXLEN];
while
(1){
n=read(sockfd,buffer,need);
if(!
n)break;
if(n<0){
if(errno==EAGAIN){
timeout++;
if(timeout>10){
break;
}
sleep
(1);
continue;
}
else{
perror("read");
returnNULL;
}
}
else{
sum_byte+=n;
timeout=0;
strncat(tmp,buffer,n);
}
}
1.5网页分析
本文采用的网页分析算法基于内容分析,通俗的讲就是遍历整个网页代码,然后找出其中所有符合限制条件的URL。
1.5.1URL提取
考虑到网页中的链接格式主要是:
title,因此本文通过string自身封装的find函数来找到每一个”herf”的位置,接下来的情况稍微有些复杂,分为三种情况。
第一种:
URL用双引号引起来;第二种:
以单引号引起来;第三种:
URL没有被引起来。
所以可以使用一个标记变量(flag)来区分以上三种情况。
1.5.2URL的重定向
考虑到本文的要求不仅仅是抓取网页本身,还要实现一个离线浏览网页的功能,原有的链接不再有效,因此,URL的重定向这一步不可缺少。
之前,爬虫已经抓取了一些网页并存放在了一个名为Pages的文件夹中,而且其中的每个网页都进行了重命名处理(本文直接以url.Fname的字符串哈希值作文保存网页的文件名)。
那么在本地的URL无论在路径和文件名上都和原来网页上的链接都是不对应的,要想实现和原来一样的网页跳转,必须修改每个链接的herf值。
对于原来的链接title,假设现在重命名该网页为new.html,那么如何处理怎么才能转化成新的链接呢?
方法有很多,比如可以通过覆盖和移动,使得两个引号直接的内容为new.html。
本文采用的方法如下:
现已知第一个引号的位置为pos_1,因此可以调用string类的insert方法。
调用后的效果如下:
title
这样处理不仅屏蔽了”xxx.html”,也避免了删除原有链接等不必要操作,一定程度上提高了代码的效率。
1.5.3URL判重
抓取网页时有一个非常棘手的问题,那就是重复抓取问题。
大家知道,一个网站中的链接非常多,抽象出来就是一个巨大的蜘蛛网,类似与图论中的无向图。
如果不对爬虫进行设置,它就像一只无头苍蝇一样,到处乱撞。
这样待抓取队列里的URL越来越多,并且好多都是重复的。
那么如何才能跳出这个怪圈呢?
C++的标准模板库已经为大家提供了一个叫set的容器(当然也可以使用hash来判重)。
在cplusplus这样介绍:
set是一种存放唯一性元素的关联容器,它里面的每一个元素都称为关键字,它由二叉搜索树实现。
由于它的唯一性,高效性,本人把它选择作为URL判重的一种类似hash的工具。
本文代码如下:
定义:
setSet;
使用:
Set.insert(hashVal);
1.5.4网页存储
前面爬虫已经抓取到了一张网页,并且进行了重定向处理。
那么接下来要做的事就是把它保存到磁盘里,在这一步需要用到文件操作。
chdir("Pages");
intfd=open(url_t.GetFname().c_str(),O_CREAT|O_EXCL|O_RDWR,00770);
/*checkwhetherneedsre-fetch*/
if(fd<0){
if(errno==EEXIST){
stat(url_t.GetFname().c_str(),&buf);
intlen=buf.st_size;
if(len>=flen)gotoNEXT;
else{
fd=open(url_t.GetFname().c_str(),O_RDWR|O_TRUNC,00770);
if(fd<0){
perror("fileopenerror");
gotoNEXT;
}
}
}
else{
perror("fileopenerror");
gotoNEXT;
}
}
write(fd,HtmFile.c_str(),HtmFile.length());
NEXT:
close(fd);
//todonext
以上代码主要功能是保存已抓取网页的内容到磁盘。
第一行代码使用O_CREAT|O_EXCL|O_RDWR模式打开,当该文件已经存在时返回-1,错误代码存放在errno中,错误代号为EEXIST。
代码中使用stat函数来读取参数为文件名的文件信息,其中我们需要的就是st_size这个成员的内容,它以字节形式记录了文件的大小。
这样就可以与当前抓取网页大小(存放于变量flen中)比较,从而判断是否需要覆盖原有文件。
本文以上代码虽然使用了不推荐的goto语句,因为程序需要跳过write函数。
不过使用goto语句在没有给程序带来混乱的情况下实现了一条break语句实现不了的功能,因此更具实用性。
1.6LinuxSocket通信
本文在这一章会涉及到LinuxSocket[14]的通信,包括TCP的连接过程,简单引用基于TCP的Socket通信下客户端的几个主要函数。
1.6.1LinuxSocket简介
前文一直提到LinuxSocket,其实,说得准确些应该是POSIX标准下的网络编程。
对于POSIX的理解,首先来参考下面一段话:
POSIX[7]表示可移植操作系统接口(PortableOperatingSystemInterface,缩写为POSIX是为了读音更像UNIX)。
电气和电子工程师协会(InstituteofElectricalandElectronicsEngineers,IEEE)最初开发POSIX标准,是为了提高UNIX环境下应用程序的可移植性。
然而,POSIX并不局限于UNIX。
许多其它的操作系统,例如DECOpenVMS和MicrosoftWindowsNT,都支持POSIX标准,尤其是IEEEStd.1003.1-1990(1995年修订)或POSIX.1,POSIX.1提供了源代码级别的C语言应用编程接口(API)给操作系统的服务程序,例如读写文件。
POSIX.1已经被国际标准化组织(InternationalStandardsOrganization,ISO)所接受,被命名为ISO/IEC9945-1:
1990标准。
其实,POSIX为用户提供了一整套给操作系统服务的应用程序接口(API),其中就包括网络通信的接口,它们可以用来提供和保障Internet中各个主机之间的通信。
由于Linux与Unix之间的深厚关系,所以在Linux平台上,那些接口也可被使用者直接调用。
1.6.2TCP/IP
在网络通信中,大家用得最多的就是TCP/IP,其实TCP/IP是一个协议族,只不过最主要的是TCP协议和IP协议。
IPv4网际协议版本是4,IPv4是IP的简称,自上世纪80年代以来一直是网际协议族的主力协议。
用32位地址来标识。
IPv4给UDP、TCP、IGMP、SCTP、和ICMP提供分组递送服务。
IPv6网际协议版本是6(InternetProtocolversion6)。
IPv6是在20世纪90年代中期为替代IPv4的所设计的。
其最大的改变是使用128位更大地址以应对20世纪90年代因特网的爆发性增长。
IPv6给UDP、TCP、SCTP和ICMPv6提供分组服务的。
本人在此论文中并未采用IPv6,而任采用目前主流的IPv4作为开发基础,实现基于TCP连接为基础的Socket通信。
选择TCP套接字通信的理由很简单,因为需要爬虫和服务器进行可靠的全双工通信(爬虫发送请求报文,与此同时,服务器处理请求报文并返回服务信息和网页代码)。
TCP传输控制协议(TransmissionControlProtoc)。
TCP是一个面向连接的协议,为用户进程提供可靠的全双工字节流。
TCP套接字是一种流套接字(streamsocket)。
TCP关心确认、超时和重传之类的细节。
大多数因特网应用程序使用TCP。
本文中的socket通信基于TCP,因此有必要提一下TCP的连接和断开过程。
TCP的可靠连接得益于它的三次握手原理,下图形象的表示了TCP三次握手建立连接和两次半关闭断开连接的具体过程。
在连接和断开连接之间,客户端和服务器即可进行双向的信息通信。
TCP三次握手与两次半关闭过程:
图1.2
1.6.3客户端Socket函数介绍
在了解各个Socket函数之前,大家首先来看一个经典的流程图1.3,几乎每次网络通信都需要走以下流程,它详细地显示了TCP客户端和TCP服务器之间的Socket通信流程:
图1.3基于TCP客户/服务器程序的套接字函数及通信流程
在程序中,每一个URL对应的网页,在客户端都需要完成Socket(),Connect(),Write(),Read(),Close()这一过程。
要注意的是,如果不及时关闭Socket文件描述符,有时会出现“opentoomanyfiles”的系统错误,这是由于系统对用户同时打开多个文件的限制(这里的文件不仅仅指通常意义上的文件,