分布式网络爬虫实验 五组 赵成龙、黄莹 一、需求分析 ................................................................. 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正则表达式库进行了两种尝试,并根据网页的情况设计了测试用例,进行程序的检验。
分布式消息队列
读取抓取的HTML
根据响应头解压缩
识别网页字符集
提取网页URL
图 网页分析模块流程图 三、模块设计及代码实现
爬取网页模块设计 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/类型
正则表达式为:]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*> (2)../a/b/类型 正则表达式为:]*href\\s*=\\s*\"\\.\\./(\\w*/)*\\.html\"\\s*> (3)./../a/b/类型 正则表达式为:]*href\\s*=\\s*\"\\./\\.\\./(\\w*/)*\\.html\"\\s*> (4)a/b/类型 正则表达式为:]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*> 然后将上述四种情况综合起来,通过“或”(即“|”)连接组成最终的提取URL的正则表达式如下:
]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"\\.\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"\\./\\.\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*>
测试用例的设计 由于两人分工,在没有得到抓取的html文件内容时,先根据上述不同四种情况设计了测试用例。作为正则表达式的待检测字符串,用来检验程序的正确性,具体如下所示:
" adfaaf134 affdsfasdf href=\"./../aff/\">afdsa ";
利用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<> #include int main() { int i,j,k; char *result[30]; char *s = " adfaaf134 affdsfasdf afdsa ";
char *pattern = "]*href\\s*=\\s*\"\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"\\.\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"\\./\\.\\./(\\w*/)*\\.html\"\\s*>|]*href\\s*=\\s*\"(\\w*/)*\\.html\"\\s*>";
m_so); m_eo); m_so,k=0;i {