当前位置:文档之家› 分布式爬虫实验设计文档

分布式爬虫实验设计文档

分布式网络爬虫实验五组赵成龙、黄莹一、需求分析 (2)二、实验架构及原理 (2)三、模块设计及代码实现 (3)爬取网页模块设计 (3)<DNS解析 (4)Socket连接 (4)发送HTTP请求头并获得相应 (6)网页解析模块设计 (7)正则表达式的设计 (8)测试用例的设计 (8)利用Regex库提取网页URL (8)利用Pcre库提取网页URL (10)》四、心得体会 (12)一、需求分析随着国际互联网的迅速发展,网上的信息越来越多,全球网页数量超过20亿,每天新增加730万网页。

要在如此浩瀚的信息海洋里寻找信息,就像“大海捞针”一样困难。

在实际生活中我们经常会使用像百度、Google这些搜索引擎检索各种信息,搜索引擎正是为了解决这个问题而出现的技术,而网络爬虫正是搜索引擎所需要的关键部分既然百度、Google这些搜索引擎巨头已经帮我们抓取了互联网的大部分信息,为什么还要自己写爬虫呢因为深入整合信息的需求是广泛存在的,在企业中,爬虫抓取下来的信息可以作为数据仓库多维展现的数据源,也可以作为数据挖掘的来源,甚至有人为了炒股,专门抓取股票信息。

这些实际问题的解决所需要的根本技术就是分布网络爬虫。

本次实验主要的内容就是利用IO复用抓取网页,并多线程的分析每个抓取到的网页所包含的URL信息,通过消息队列将抓取网页的部分和分析网页部分进行通信,最终记录下160000网页中所包含的所有URL,实现分布式网络爬虫。

》二、实验架构及原理本实验分为两个模块:爬取网页模块、网页分析模块。

实验架构如图所示图分布是网络爬虫框架爬取网页模块采用socket通信方式实现客户端与服务器的通信:首先将客户端与服务器进行三次握手后建立连接,客户端发送HTTP请求头,服务器端收到客户端请求后,进行HTTP响应,发送相应的网页信息,客户端收到服务器的响应后将所获得网页文件交给网页分析模块进行处理并提取URL。

流程图如图所示:图爬取网页模块流程图网页分析模块主要工作如下图流程图所示。

而本模块的网页分析处理主要在于对抓取到的HTML文件的内容进行URL的提取,我们主要运用正则表达式进行字符串的匹配操作。

通过采用Regex正则表达式库和Pcre正则表达式库进行了两种尝试,并根据网页的情况设计了测试用例,进行程序的检验。

!图网页分析模块流程图三、模块设计及代码实现爬取网页模块设计DNS解析考虑到网页爬取域名转换的问题,需要将URL进行DNS解析。

DNS解析是将一一对应的域名与IP地址进行转换的一种技术,域名解析需要由专门的域名解析服务器来完成,整个过程是自动进行的。

首先利用接口struct hostent *gethostbyname(const char *name)将需要解析的域名名称作为参数传入到函数中,然后函数执行后返回一个结构体hostent,其中包括了域名所对应的ip地址列表信息。

具体代码如下:char* dns_decode(char host[]){?struct hostent* ht=NULL;struct in_addr* tmp;char *dns[20];int i=0;if((ht=gethostbyname(host))==NULL){herror("gethostbyname wrong!\n");return NULL;~}else{printf("get the host:%s\n",host);while(tmp=(struct in_addr*)*ht->h_addr_list) {dns[i]=(char *)inet_ntoa(*tmp); printf("IP:%s\n",dns[i]);(i++;a/b/类型正则表达式为:<a\\s*[^>]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*>(2)../a/b/类型正则表达式为:<a\\s*[^>]*href\\s*=\\s*\"\\.\\./(\\w*/)*\\.html\"\\s*>(3)./../a/b/类型正则表达式为:<a\\s*[^>]*href\\s*=\\s*\"\\./\\.\\./(\\w*/)*\\.html\"\\s*>(4)a/b/类型)正则表达式为:<a\\s*[^>]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*>然后将上述四种情况综合起来,通过“或”(即“|”)连接组成最终的提取URL的正则表达式如下:<a\\s*[^>]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*>|<a\\s*[^>]*href\\s*=\\ s*\"\\.\\./(\\w*/)*\\.html\"\\s*>|<a\\s*[^>]*href\\s*=\\s*\"\\./\\.\\./(\\w*/) *\\.html\"\\s*>|<a\\s*[^>]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*>测试用例的设计由于两人分工,在没有得到抓取的html文件内容时,先根据上述不同四种情况设计了测试用例。

作为正则表达式的待检测字符串,用来检验程序的正确性,具体如下所示:"<a href=\"./abc/def/\"> adfaaf134 <a href =\"../a/\">affdsfasdf <a href=\"./../aff/\">afdsa <a class=\"ada\" href=\"\">";:利用Regex库提取网页URL首先利用了Regex正则表达式库进行URL的字符串匹配。

采用接口int regcomp(regex_t *preg, const char *pattern, int cflags) 将要进行匹配的正则表达式进行编译,做匹配前的准备工作。

编译后采用int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[],int eflags)用来检测字符串是否匹配正则表达式,具体的相应代码如下:#include<>#include<>#include<sys/>int main()<{int i,j,k;char *result[30];char *s = "<a href=\"./abc/def/\"> adfaaf134 <a href =\"../a/\">affdsfasdf <a href=\"./../aff/\">afdsa <a class=\"ada\" href=\"\">";char *pattern = "<a\\s*[^>]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*>|<a\\s*[^>]*href\\s*=\\s* \"\\.\\./(\\w*/)*\\.html\"\\s*>|<a\\s*[^>]*href\\s*=\\s*\"\\./\\.\\./(\\w*/)*\ \.html\"\\s*>|<a\\s*[^>]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*>";m_so);m_eo);^m_so,k=0;i<pmatch[0].rm_eo&&k<200;i++,k++){result[j][k]=(s+offset)[i];m_eo;result[j][k]='\0';printf("%s\n",result[j]);}~}在linux环境下编译并执行上述C程序,并将结果打印如来,如下图所示。

图 Regex库匹配结果然而利用Regex库通过多次调试发现只能将整个标签<a>提取出来,但是无法将标签<a>中的href后两个双引号中具体的.hmtl文件获取出来。

其实通过正则表达式规范的零宽断言是可以做到的,但是Regex库并不支持零宽断言,即当满足某个条件式时,匹配出后面的字符串。

因此选择更符合要求的Pcre库进行匹配提取。

/利用Pcre库提取网页URLPcre是一个很强大的正则库,它是perl语言兼容正则表达式,是一种用C语言写的正则库。

利用Pcre库与Regex道理类型,即首先采用pcre *pcre_compile(const char*pattern, int options,const char **errptr, int *erroffset,const unsigned char *tableptr)来编译我们的正则表达式。

在进行编译正则表达式时设置了PCRE-DOTALL这个修饰符, 模式中的点号元字符匹配所有字符, 包含换行符。

如果没有这个修饰符, 点号是不匹配换行符。

这也是考虑到有时候这个标签<a>在html文件中会出现在换行的位置。

编译后采用int pcre_exec(const pcre *code, const pcre_extra *extra,const char*subject, int length, int startoffset,int options, int *ovector, int ovecsize)来执行正则匹配。

其中ovector为匹配成功后所匹配的子串在字符串中的位置,数组中第一位为第一个匹配结果的开始位置,第二个表示结束位置,第三个表示在有子串时第一个子串的开始位置,第四个表示第一个子串的结束位置,然后以此类推。

相关主题