【具体实施方式】
下面结合具体实施例及附图对本发明作进一步详细说明。下面详细描述本发明的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,仅用于解释本发明的技术方案,而不应当理解为对本发明的限制。
在本发明的描述中,术语“内”、“外”、“纵向”、“横向”、“上”、“下”、“顶”、“底”等指示的方位或位置关系为基于附图所示的方位或位置关系,仅是为了便于描述本发明而不是要求本发明必须以特定的方位构造和操作,因此不应当理解为对本发明的限制。
本发明提供一种应用于单台多核处理器主机的多线程网络爬虫执行方法。如图1所示,本发明提出的应用于单台多核处理器主机的多线程网络爬虫执行方法,包括以下步骤:S10、基于主机处理器核数以及线程数量创建网页爬取线程、网页分析线程以及URL种子线程,申请哈希表空间;S20、获取包含URL列表的初始URL种子文件,将所述初始URL种子文件中的URL种子载入URL种子缓冲队列;S30、网页爬取线程从URL种子缓冲队列中取出URL种子块,采用仅遍历URL种子块中URL条目的策略进行网页爬取;S40、当爬取的网页数量达到网页爬取线程设定的最大阈值时,将网页内容和其对应的URL封装并载入网页缓冲队列;S50、网页分析线程每次从网页缓冲队列中取出一个队列元素,并对所述队列元素中每一个网页通过查询哈希表进行URL分析,排除重复出现的URL,将新出现的URL载入待爬取URL列表;S60、当待爬取URL列表中元素达到最大值时写入URL缓冲队列,当一个网页缓冲队列元素中所有网页被分析后,将元素对象***网页磁盘缓存,由清空网页缓存线程写入磁盘;S70、URL种子生成线程每次从URL缓冲队列中取出URL列表并重排,封装成URL种子块并***URL种子缓冲队列。
如图2所示,本发明提出的应用于单台多核处理器主机的多线程网络爬虫框架执行过程主要有URL种子生成、网页爬取、网页分析(包括URL去重)、将网页数据写入磁盘等。其间使用了URL种子缓冲队列、网页缓冲队列及URL缓冲队列减少线程通信和磁盘访问次数来提高***的效率。未在图中标出的过程有初始化过程及结束清理过程。用户在该框架之上编写自己的网络爬虫时只需重写“清空网页缓存区”方法来自定义文件的输出格式,其它部分不需要进行改动。
用户在机器上部署本框架***时,可通过框架的XML配置文件自定义网页爬取线程、网页分析线程、生成种子线程的数目及各缓存区大小。如不进行自定义配置,***将根据预定义的运行策略表自动匹配在当前机器上最优的执行方案。
本框架所设计的各个线程执行的周期不同,其中工作量最大的网页爬取线程和网页分析线程需要一直循环执行并尽量不使其发生等待;生成URL种子线程工作量适中,有一定时间内生成URL种子线程将处于等待状态;清空网页缓存区线程、装载URL缓存区线程及清空URL缓存区线程工作量最小,大部分时间处于等待状态。根据以上知识指导设计最优策略表,并根据大量实验得出最优策略表如下:
针对目前常用的商用多核处理器,按照以下方案自动获得CPU的逻辑内核数并进行匹配:
(1)双核处理器:1个网页爬取线程、1个网页分析线程,1个生成URL种子线程;
(2)四核处理器或双核四线程处理器:1个网页爬取线程、2个网页分析线程、1个生成URL种子线程;
(3)六核处理器:2个网页爬取线程、2个网页分析线程、1个生成URL种子线程;
(4)八核处理器或四核八线程处理器:2个网页爬取线程、3个网页分析线程、1个生成URL种子线程;
(5)六核十二线程处理器:4个网页爬取线程、5个网页分析线程、1个生成URL种子线程;
(6)八核十六线程处理器:5个网页爬取线程、7个网页分析线程、2个生成URL种子线程。
在本框架之上开发网络爬虫程序时需要提供一个初始URL种子文件,该文件内容为若干条用户感兴趣的URL列表。框架首先通过初始化模块申请哈希表空间,创建所有线程,并将用户提供的初始种子文件中的URL种子加载入URL种子缓冲队列中,种子缓冲队列的结构如图3所示,其元素为一个URL种子块的地址或指针变量,每个变量指向一个存储在堆空间中的600条URL列表组成的种子块对象。此时其他线程处于等待状态,网页爬取线程(如图4所示)从URL种子缓冲队列中取出URL种子块对象进行网页爬取,爬取时仅遍历URL种子数据块中的URL条目,而不进行更深一层的宽度优先搜索。因为本框架能够保证URL种子缓冲队列中的所有URL条目均不重复,所以用这些URL种子进行网页爬取的所有网页爬取线程所获得网页内容也均不重复(不考虑URL不同但网页内容相同的情况)。当爬取的网页数量达到网页爬取线程设定的最大值500时,将网页内容写入网页缓冲队列中。写入前需将网页内容和其对应的URL封装成为网页缓冲队列的元素对象,如图4所示,网页缓冲队列的元素为100条URL和其相应的网页内容这样一对值的顺序排列组成。网页分析线程(如图4所示)每次从网页缓冲队列中摘下一个队列元素,对元素中每一个网页进行URL分析,通过查询哈希表,检查每个经过网页分析所提取到的URL是否重复出现,若是新的URL则加入待爬取URL列表中。当待爬取URL列表达到最大值时将其写入URL缓冲队列中。当一个网页缓冲队列元素中所有网页都已被分析后,将该元素对象***网页磁盘缓存中,由清空网页缓存线程定期写入磁盘。URL缓冲队列的内容即为URL种子生成线程的源数据,URL种子生成线程每次从URL缓冲队列中摘下5个元素的URL列表,将这些URL重新排列,封装成5个URL种子块***URL种子缓冲队列中。至此,网络爬虫的一个工作循环已完成。
在本发明提出的应用于单台多核处理器主机的多线程网络爬虫执行方法中,采用基于位验证的两次哈希去重方法创建所述哈希表,所述两次哈希去重方法包括ELFhash变型算法以及HFIp型URL哈希算法。设计哈希表的目标是为10亿量级的URL条目进行去重操作。为节省内存资源,不考虑处理冲突的键,因为要检测冲突键需要存储URL键值,而URL占用存储空间较多。本方案在此只存储某个哈希值是否已被查询的状态,被查询或未被查询状态用一个bit就可以表示。为存储10亿条URL记录的哈希状态,最多需要长度为109/8=1.25*108的char型数组hashTable[1.25*108](一个char型变量有8位),该数组所占用内存约为125MB。为访问到数组元素char中每个位的值,设置一个长度为8的掩码数组mask[8]。从mask[0]、mask[1]到mask[7],它们的值分别是:0x00000001,0x00000010,0x00000100,0x00001000,0x00010000,0x00100000,0x01000000,0x10000000。访问URL的哈希值状态的步骤为:(1)计算URL的哈希值(hashValue):hashValue=哈希函数(URL)。(2)该URL的哈希状态hashStatus=hashTable[hashValue/8]^mask[hashValue%8]。哈希状态(hashStatus)的值分为0和非0两种,0表示此URL未出现过,非0表示此URL出现过,哈希表中所有元素初始值都为0。
当哈希表的规模增大时,哈希函数的不均匀率即冲突率也会随之升高,从而使发生误判的概率增加。例如当某URL1与另一URL2发生碰撞时,会误判URL2与URL1重复。考虑到不同哈希算法分布差异很大,可以认为相同URL键在两个计算过程不同的哈希函数中发生碰撞这两个事件关联性很小。可以近似的认为同一键在这两个哈希函数下同时发生碰撞的概率为两个函数冲突率之积。因此再增加一张同样规模的哈希表,采用数学过程差别较大的的哈希算法,每次计算URL的两种哈希值,并分别到两个表进行查询,只要其中一个表中状态位为0,就说明该URL不重复。即该URL的最终哈希状态为哈希函数表1状态与哈希函数表2状态的或运算。查询的过程将两个哈希表中的该URL哈希值对应的位都置1表示该URL已出现过。如图6所示,在选用哈希算法时,尽量选用对URL哈希值分布均匀且计算速度快的算法,本***中采用一个ELFhash算法的变型如代码1所示,进行哈希值的计算,另一个算法为常用的URL哈希算法HFIp如代码2所示。由实验数据得知两种算法在进行大规模URL集的哈希查找时,性能较为优越,且统计均匀性较好。
本方案中网页爬取模块仅仅按照URL种子中的URL列表抓取网页,而不进行进一步的搜索。因此使网页爬取模块阶段不产生重复问题,网页爬取线程将获得的网页内容写入网页缓冲队列,网页分析线程从网页缓冲队列中取网页数据,分析提取网页中的URL,并将这些URL去重后放入URL缓冲队列中。此时由于从同一个网页中提取的URL相邻存储,一般情况下直接将这些URL作为种子给网页爬取线程按照广度优先搜索进行网页爬取,这种情况下会造成在短时间内大量访问同一域名下的URL,即“礼貌”爬行问题。在将搜索步骤与网页爬取线程解耦后,原本在网页爬取线程内部的完成广度优先搜索现在成为宏观尺度上的广度优先搜索,即网页爬取线程、网页分析线程、URL种子生成线程共同构成URL的广度优先搜索。在种子生成线程中从URL缓存列表中一次提取大量URL(5*600=3000条)进行随机重排,使得来自各个域名的URL均匀的分布。然后将打乱次序的URL封装成种子块***URL种子缓冲队列。此时网页爬取线程用乱序种子进行网页爬取,这样能能很好的避免“礼貌”爬取问题。
在本发明中,如图7所示,为网页缓冲队列、URL缓冲队列、URL种子缓冲队列统一设定生产阈值为0.2,该生产阈值的作用为:当各个缓冲队列中的元素数量小于等于缓冲区总长度的20%时,立即唤醒各缓冲队列的生产者线程为缓冲队列填充数据。网页缓冲队列的生产者线程为网页爬取线程,消费者为网页分析线程;URL缓冲队列的生产者线程为网页分析线程,消费者为清空URL缓存区线程;URL种子缓冲队列的生产者线程为URL种子生成线程,消费者为网页爬取线程。本方案中在各缓冲队列在到达生产阈值时就主动唤醒生产者线程,而此时缓冲队列还有20%的数据,消费者线程就能够不用等待生产者线程补充缓冲区而继续工作,由此提高了消费者线程与生产者线程之间的并行度。相应的,为网页缓冲队列、URL缓冲队列、URL种子缓冲队列统一设定消费阈值为0.8,当各个缓冲队列中的元素数量大于等于缓冲区总长度的80%时,唤醒各个缓冲队列的消费者线程从缓冲队列中取出数据。该消费阈值的作用为:当各个缓冲队列中的元素数量大于等于缓冲区总长度的80%时,唤醒各个缓冲队列的消费者线程为缓冲队列清空数据。
本发明通过构建一个适用于单台商用多核处理器主机上多线程通用网络爬虫框架,并合理设计各线程的工作负载,从而优化网络爬虫程序在单台多核处理器主机上运行的效率。本发明具有如下特点:
(1)分解基于广度优先搜索的网页爬取,由网页爬取线程、网页分析线程、种子生成线程和URL种子缓冲队列、网页缓冲队列、URL缓冲队列共同完成宏观尺度的基于广度优先搜索的网页爬取。这样针对工作量大的网页爬取线程和网页分析线程可根据处理器的核心数目多启动若干数量的这两种线程以充分发挥多核处理器的性能。为不同核心数目的常见商用处理器设计了一个可自动匹配的执行计划策略表,根据次策略表可自动匹配得到当前机器的最优执行方案,即按照此配置能达到工作负载最均衡的状态,避免额外的线程切换或等待,将程序在当前多核处理器上的性能最大化。
(2)提出低内存消耗,低误判的两次哈希URL去重模型,使得本框架***在进行10亿量级的URL的去重操作时仅需要125MB*2=256MB的内存空间。远远少于一般采用完全内存方式的去重模型的内存需求量,为5G-8G或5G-8G的1/8即600M-1G。若一般完全内存方式的去重模型URL重复误判率为x,则本方案的URL重复误判率为x2,误判率大大降低。
(3)采用简单有效的随即乱序种子生成代替分布式爬虫方案中广泛采用的Web划分方式,在一定程度上解决了“礼貌”爬取问题,且相比Web划分方式执行效率更高。
(4)为框架内的缓冲队列设定生产阈值与消费阈值,增加了各线程如网页爬取线程、网页分析线程、URL种子生成线程、清空URL缓存区线程之间的并行度,提高了多核CPU的利用率。
虽然本发明参照当前的较佳实施方式进行了描述,但本领域的技术人员应能理解,上述较佳实施方式仅用来解释和说明本发明的技术方案,而并非用来限定本发明的保护范围,任何在本发明的精神和原则范围之内,所做的任何修饰、等效替换、变形、改进等,均应包含在本发明的权利要求保护范围之内。