您的当前位置:首页正文

分布式网络爬虫设计文档

2022-02-20 来源:好走旅游网


分布式网络爬虫设计文档

刘祎睿 陈蔚瀚 李嘉

一、实验目标:

本次实验目标为设计一个分布式网络爬虫实现一下功能:

1. 从一个给定的网址中分析其所包含的URL并爬取对应的网页,直到爬取完全部不重复的网页为止。

2. 支持分布式爬取,同时记录输出每一个网页的大小。

3. 采用多线程结构设计,实现高性能的网络爬虫。

二、整体架构设计:

本系统整体架构如下图,由主线程、异步抓取线程、网页解析线程三类线程构成,其中,网页分析线程由网页分析线程池统一分配调度。线程间的通信由网页结果队列和URL人任务队列负责,两个消息队列由轻量级消息队列Nanomsg创建采用Pipeline模式。主线程主要负责异步抓取线程和网页解析线程池的创建。异步抓取线程主要负责从URL任务队列中获取网页网址,然后完成网页的Socket抓取,并将得到的网页存入网页结果队列中。网页解析线程池主要负责分配网页解析线程从网页结果队列提取网页进行分析。网页解析线程主要负责从网页内容中提取出有效的URL并存入URL任务队列。

三、架构实现要点:

完成本爬虫系统主要需要实现两个核心线程,分别是异步抓取线程和网页解析线程。

1. 异步抓取线程设计

抓取线程主要靠Libevent库来实现,Libevent库是一个基于Reactor模型的一个网络库,支持异步的调用函数。只需在初始化的时候在相应时间上一个函数,程序就会在该事件发生时调用对应的函数库。

为了实现通过Libevent完成网页的连接和抓取,需要注册两个事件receiveResponse_cb和eventcb,其中receiveResponse_cb负责读取,eventcb负责设置判断是否发生建立连接事件,超时事件读取结束事件等。

线程的整体逻辑如下图,首先完成相关事件注册,然后让线程处于循环查询状态,判断相关事件是否发生,如果定时事件被触发,爬取线程就会从URL任务队列中读取URL,然后通过Socket建立网络连接,并将连接事件加入队列。如果连接建立时间被触发,则爬

取线程会向服务器发送HTTP请求。当连接数据事件到达事件被触发,爬取线程会读取HTTP响应,并将网页内容放入网页结果队列。

2. 网页解析线程设计

网页解析线程主要负责解析HTML语言,通过使用有限状态自动机提取HTML中出现的有效连接,并将URL链接存入URL任务队列中。其整体流程如下:

(1) 从网页结果队列中读取抓取HTML

(2) 识别匹配网页字符集

(3) 提取网页中的有效URL

(4) 将提取出的URL放入URL队列中

从HTML中提取链接所使用的有效状态自动机如下图:

HTML链接中的URL主要放在标签中的href属性中,我们采用的状态机的方式提取出标签中的URL。分析时也需要去除href=”#”、href=”javascript::void(0)”等这样的无效链接,对于href=”a.html#a1”这样的锚点链接,我们要将后面的锚点去掉,只留下a.html。这样在去重的时候,能够保证不将a.html#a1和a.html#a2视为两个链接。同时我们需要把相对URL地址转化为绝对地址。并将URL中无效的部分剔除掉,如某些URL后会包含?XXXXXXX,这些对于URL地址都是无效的。

在提取过程中我们还要完成URL的去重工作,避免反复抓取同一个URL地址。在本次实验中,使用的是实验一大规模字符串查找中的TRIE树来进行查重。在使用TRIE树的时候,需要注意进行线程的同步。由于上一个实验的代码是单线程的程序,所以TRIE树的插入、查找的操作也是单线程的。所以在使用时需要用pthread_mutex_t来进行线程间的同步与互斥操作。

3. 消息队列设计

消息队列采用的是Nanomsg库,这是一个使用C语言编写的一个消息队列,可以轻

松完成跨线程、跨进程、跨机器的通讯。Nanomsg的通讯模式有NN_PAIR、NN_REPREQ、NN_PIPELINE等通讯模型。本程序采用的通讯模型主要是NN_PIPLINE的通讯模型,它是一种单向的通信,其通信模型如下图:

4. 线程池

进程池线程主要采用的是threadpool.c和threadpool.h这两个文件。其中,create_threadpool函数新建了一个线程池,并将线程池进行初始化操作。在实际需要调用线程的时候,只需要使用dispatch函数,将要调用的函数指针、参数传递进去。线程池会自动给你调用执行并回收资源。通过线程池可以很好的控制分析线程运行的个数,做到按需来分配线程,避免了因频繁生成和销毁线程造成的线程开销。

四、实验结果:

经过多次运行,该程序总共分析出了个 153596链接地址,总共文件大小为10458295052字节