分布式网络爬虫实验五组赵成龙、黄莹一、需求分析..................................................................................................................................2二、实验架构及原理......................................................................................................................2三、模块设计及代码实现..............................................................................................................33.1爬取网页模块设计............................................................................................................33.1.1DNS解析.................................................................................................................43.1.2Socket连接.............................................................................................................43.1.3发送HTTP请求头并获得相应.............................................................................63.2网页解析模块设计............................................................................................................73.2.1正则表达式的设计.................................................................................................83.2.2测试用例的设计.....................................................................................................83.2.3利用Regex库提取网页URL..................................................................................83.2.4利用Pcre库提取网页URL..................................................................................10四、心得体会................................................................................................................................12一、需求分析随着国际互联网的迅速发展,网上的信息越来越多,全球网页数量超过20亿,每天新增加730万网页。要在如此浩瀚的信息海洋里寻找信息,就像“大海捞针”一样困难。在实际生活中我们经常会使用像百度、Google这些搜索引擎检索各种信息,搜索引擎正是为了解决这个问题而出现的技术,而网络爬虫正是搜索引擎所需要的关键部分既然百度、Google这些搜索引擎巨头已经帮我们抓取了互联网的大部分信息,为什么还要自己写爬虫呢?因为深入整合信息的需求是广泛存在的,在企业中,爬虫抓取下来的信息可以作为数据仓库多维展现的数据源,也可以作为数据挖掘的来源,甚至有人为了炒股,专门抓取股票信息。这些实际问题的解决所需要的根本技术就是分布网络爬虫。本次实验主要的内容就是利用IO复用抓取网页,并多线程的分析每个抓取到的网页所包含的URL信息,通过消息队列将抓取网页的部分和分析网页部分进行通信,最终记录下160000网页中所包含的所有URL,实现分布式网络爬虫。二、实验架构及原理本实验分为两个模块:爬取网页模块、网页分析模块。实验架构如图2.1所示图2.1分布是网络爬虫框架爬取网页模块采用socket通信方式实现客户端与服务器的通信:首先将客户端与服务器进行三次握手后建立连接,客户端发送HTTP请求头,服务器端收到客户端请求后,进行HTTP响应,发送相应的网页信息,客户端收到服务器的响应后将所获得网页文件交给网页分析模块进行处理并提取URL。流程图如图所示:图2.2爬取网页模块流程图网页分析模块主要工作如下图流程图所示。而本模块的网页分析处理主要在于对抓取到的HTML文件的内容进行URL的提取,我们主要运用正则表达式进行字符串的匹配操作。通过采用Regex正则表达式库和Pcre正则表达式库进行了两种尝试,并根据网页的情况设计了测试用例,进行程序的检验。分布式消息队列读取抓取的HTML根据响应头解压缩识别网页字符集提取网页URL图2.3网页分析模块流程图三、模块设计及代码实现3.1爬取网页模块设计3.1.1DNS解析考虑到网页爬取域名转换的问题,需要将URL进行DNS解析。DNS解析是将一一对应的域名与IP地址进行转换的一种技术,域名解析需要由专门的域名解析服务器来完成,整个过程是自动进行的。首先利用接口structhostent*gethostbyname(constchar*name)将需要解析的域名名称作为参数传入到函数中,然后函数执行后返回一个结构体hostent,其中包括了域名所对应的ip地址列表信息。具体代码如下:char*dns_decode(charhost[]){structhostent*ht=NULL;structin_addr*tmp;char*dns[20];inti=0;if((ht=gethostbyname(host))==NULL){herror(gethostbynamewrong!\n);returnNULL;}else{printf(getthehost:%s\n,host);while(tmp=(structin_addr*)*ht-h_addr_list){dns[i]=(char*)inet_ntoa(*tmp);printf(IP:%s\n,dns[i]);i++;//printf(IP:%s\n,inet_ntoa(*tmp));ht-h_addr_list++;}}returndns[0];}3.1.2Socket连接Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。下图是socket建立连接的流程图:图3.1socket建立连接流程图服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。本模块实现的是客户端,首先初始化好网页所在服务器的ip地址及端口号,然后通过intconnect(intsockfd,conststructsockaddr*server_addr,socklen_taddrlen)函数连接到服务器端,为之后发送HTTP请求头做准备。具体代码如下:intopen_socket(structin_addrserver_ip){intclient_sock;structsockaddr_inserver_addr;client_sock=socket(AF_INET,SOCK_STREAM,0);if(client_sock0){printf(socketerror\n);return-1;}bzero(&server_addr,sizeof(server_addr));server_addr.sin_family=AF_INET;//server_addr.sin_addr.s_addr=htonl(server_ip.s_addr);server_addr.sin_addr.s_addr=server_ip.s_addr;server_addr.sin_port=htons(80);if(connect(client_sock,(structsockaddr*)&server_addr,sizeof(structsockaddr))==-1){printf(connecterror!\n);return-1;}printf(opensuccess!\n);returnclient_sock;}3.1.3发送HTTP请求头并获得相应(1)客户端要向服务器发送一个HTTP请求头,然后服务器根据HTTP请求头的内容响应信息发送回给客户端。请求头内容如下所示:char*head_info[]={GET/index.htmlHTTP/1.1\r\n,HOST:192.168.137.0\r\n,User-Agent:Mozilla/5.0(X11;Linuxi686;rv:24.0)Gecko/20100101Firefox/24.0\r\n,Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n,Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n,//Accept-Encoding:gzip,deflate\r\n,Connection:keep-alive\r\n,\r\n,NULL};其中:Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3客户端支持的语言分别是中文和简体中文,优先支持简体中文。Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8客户端支持的MIME类型分别是text/html、application/xhtml+xml、application/xml和*/*,优先顺序是它们从左到右的排列顺序。Accept-Encoding:gzip,deflate客户端支持的压缩编码是gzip和deflate。Host:域名Host表示请求的服务器网址;Connection:Keep-AliveConnection表示客户端与服务连接类型;Keep-Alive表示持久连接;(2)HTTP响应信息在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行(statusline)通过提供一个状态码来说明所请求的资源情况。最常用的状态码如下:2.最常用的状态码有:200(OK):找到了该资源,并且一切正常。304(NOTMODIFIED):该资源在上次请求之后没有任何修改。这通常用于浏览器的缓存