摘自http://blog.sina.com.cn/s/blog_6cc084c90100nf39.html

---------------------------------------------------------------------------------

一.利用ELFHash策略多线程抓取网页

这些天看了其它小组的博客,发现大家用Heritrix抓取所花的时间都比较长,基本都要花上数天的时间才能抓完,名副其实的爬虫…之所以这么慢,一个重要的原因是heritrix在抓取时一般只运行了一个线程。在网上查找原因,得知这是因为在默认的情况下,Heritrix使用HostnameQueueAssignmentPolicy来产生key值,而这个策略是用hostname作为key值的,因此一个域名下的所有链接都会被放到同一个线程中去。如果对Heritrix分配URI时的策略进行改进,利用ELF hash算法把url尽量平均分部到各个队列中去,就能够用较多的线程同时抓取一个域名下的网页,速度将得到大大的提高。

具体的做法如下:

1.在org.archive.crawler.frontier下新建一个ELFHashQueueAssignmentPolicy类,这个类要注意继承自 QueueAssignmentPolicy。

2.在该类下编写代码如下:

 public class ELFHashQueueAssignmentPolicy extends QueueAssignmentPolicy{
@Override
public String getClassKey(CrawlController controller, CandidateURI cauri) {
return this.ELFHash(cauri.getUURI().toString(), 50) + "";
} public int ELFHash(String str, int number) {
int hash = 0;
long x = 0l;
char[] array = str.toCharArray();
for (int i = 0; i < array.length; i++) {
hash = (hash << 4) + array[i];
if ((x = (hash & 0xF0000000L)) != 0) {
hash ^= (x >> 24);
hash &= ~x;
}
}
int result = (hash & 0x7FFFFFFF) % number;
return result;
}
}

3.  修改AbstractFrontier 类的AbstractFrontier方法 :

关键代码段是:

String queueStr = System.getProperty(AbstractFrontier.class.getName() +
                 "." + ATTR_QUEUE_ASSIGNMENT_POLICY,
                  ELFHashQueueAssignmentPolicy.class.getName() + " " +

HostnameQueueAssignmentPolicy.class.getName() + " " +

IPQueueAssignmentPolicy.class.getName() + " " +

BucketQueueAssignmentPolicy.class.getName() + " " +

SurtAuthorityQueueAssignmentPolicy.class.getName());

Pattern p = Pattern.compile("\\s*,\\s*|\\s+");

String [] queues = p.split(queueStr);

其中红色部分是新加的代码。

4.  修改heritrix.properties 中的配置

#############################################################################
        # F R O N T I E R                                                          
        #############################################################################

# List here all queue assignment policies you'd have show as a
        # queue-assignment-policy choice in AbstractFrontier derived Frontiers
        # (e.g. BdbFrontier).
        org.archive.crawler.frontier.AbstractFrontier.queue-assignment-policy = \

org.archive.crawler.frontier.ELFHashQueueAssignmentPolicy \

org.archive.crawler.frontier.HostnameQueueAssignmentPolicy \

org.archive.crawler.frontier.IPQueueAssignmentPolicy \

org.archive.crawler.frontier.BucketQueueAssignmentPolicy \

org.archive.crawler.frontier.SurtAuthorityQueueAssignmentPolicy \

org.archive.crawler.frontier.TopmostAssignedSurtQueueAssignmentPolicy

org.archive.crawler.frontier.BdbFrontier.level = INFO

红色部分为新加部分。

添加代码后运行的结果如下图,可见Heritrix已经在开50个线程同时抓取网页。

抓取速度得到了很大的提高,1.4G的网页8个多小时就抓好了。在Hosts栏里显示,只抓取了ccer.pku.edn.cn域名下的网页。

</:O:P>

一些分析:

1)添加的ELFHash算法程序并不算很复杂。ELFhash算法的基本思想是:将一个字符串的数组中的每个元素依次按前四位与上一个元素的低四位相与,组成一个长整形,如果长整的高四位大于零,那么就将它折回再与长整的低四位相异或,这样最后得到的长整对HASH表长取余,得到在HASH中的位置。

2)ELFHash函数将输入的字符串进行哈希计算,输出算出的整数型哈希值。getClassKey函数中调用了ELFHash函数计算出哈希值,转换为字符串型返回上一层。之所以取模100是因为一般情况下Heritrix开100个线程,对应100个不同的URI处理队列。

3)  QueueAssignmentPolicy类源程序里的说明:

* Establishes a mapping from CrawlURIs to String keys (queue names).

* Get the String key (name) of the queue to which the

* CrawlURI should be assigned.

*

* Note that changes to the CrawlURI, or its associated

* components (such as CrawlServer), may change its queue

* assignment.

可知该类建立抓取到的URI和抓取队列名之间的映射。这个类是个抽象类,不同的策略由不同的子类实现,如根据域名、IP等。

4)AbstractFrontier类是调度器基本实现类,是一个非常复杂的类,没有仔细研究。这里加在里面的程序作用大概是将ELFHashQueueAssignmentPolicy这个策略加入到运行时所使用的URI分配策略中。在heritrix.properties中的修改也同样为这个目的。

5)由上可见使用这个策略后,速度有了非常大的提高。但抓下来的1.4G数据相比之前抓下来的有点小,大概是max-retries值设置得太低(原来是30,改为5),导致不少东西没有抓下来。

二.只抓取HTML对象

由上面的图可以知道抓取的内容中有一些不需要用到的文件类型,比如pdf,jpeg等等。如何用Heritrix只抓特定的对象,比如只抓HTML型的。Heritrix的官方文档”Heritrix User Manual”中A.3节给出了一个解决方案:

1)You would first need to create a job with the single seed http://foo.org/bar/. You'll need to add the MirrorWriterProcessor on the Modules screen and delete the ARCWriterProcessor. This will store your files in a directory structure that matches the crawled URIs, and the files will be stored in the crawl job's mirror directory.

2)Your job should use the DecidingScope with the following set of DecideRules:

RejectDecideRule

SurtPrefixedDecideRule

TooManyHopsDecideRule

PathologicalPathDecideRule

TooManyPathSegmentsDecideRule

NotMatchesFilePatternDecideRule

PrerequisiteAcceptDecideRule

We are using the NotMatchesFilePatternDecideRule so we can eliminate crawling any URIs that don't end with .html. It's important that this DecideRule be placed immediately before PrerequisiteAcceptDecideRule; otherwise the DNS and robots.txt prerequisites will be rejected since they won't match the regexp.

3)On the Setting screen, you'll want to set the following for the NotMatchesFilePatternDecideRule:

decision: REJECT

use-preset-pattern: CUSTOM

regexp: .*(/|\.html)$

根据需要,将正则表达式进行修改以满足需要,在这里更改为:

(.*(/|\.(html|htm|xml|asp))$)|(.*\.asp\?.*)
    抓取的效果如下图所示:

三.取消Robots.txt的限制

Robots.txt是一种专门用于搜索引擎网络爬虫的文件,当构造一个网站时,如果作者希望该网站的内容被搜索引擎收录,就可以在网站中创建一个纯文本文件robots.txt,在这个文件中,声明该网站不想被robot访问的部分。这样,该网站的部分或全部内容就可以不被搜索引擎收录了,或者指定搜索引擎只收录指定的内容。因为大部分的网站并不会放置一个robots.txt文件以供搜索引擎读取,所以 Heritrix爬虫在抓取网页时会花费过多的时间去判断该Robots.txt文件是否存在,从而增加了抓取时间。好在这个协议本身是一种附加协议,完全可以不遵守。

在Heritrix中,对robots.txt文件的处理是处于PreconditionEnforcer这个Processor中的。PreconditionEnforcer是一个Prefetcher,当处理时,总是需要考虑一下当前这个链接是否有什么先决条件要先被满足的,而对robots.txt的访问则正好是其中之一。在PreconditionEnforcer中,有一个private类型的函数,函数声明为: private boolean considerRobotsPreconditions(CrawlURI curi)  。该函数的含义为:在进行对参数所表示的链接的抓取前,看一下是否存在一个由robots.txt所决定的先决条件。该函数返回true时的含义为需要考虑robots.txt文件,返回false时则表示不需要考虑robots.txt文件,可以继续将链接传递给后面的处理器。所以,最简单的修改办法就是将这个方法整个注释掉,只返回一个false值。

网上声称使用这种办法可以提高抓取速度一半以上,由于抓取所花时间比较多,没有进行对比比较。以上的抓取都是在去除robots.txt情况下进行的。

[转载]Heritrix 提高效率的若干方法的更多相关文章

  1. PhpStorm提高效率的使用方法及设置

    快捷键: CTRL + D  复制当前行到下一行 或 复制选中内容到选中内容之后 CTRL + Y  删除当前行或选中内容所涉及的行 CTRL + R  替换 CTRL + F  查找 ALT + 上 ...

  2. PhpStorm提高效率的使用方法及设置(快捷键)

    原文链接:https://my.oschina.net/chunto/blog/262954 快捷键: CTRL + D  复制当前行到下一行 或 复制选中内容到选中内容之后 CTRL + Y  删除 ...

  3. sql的简单提高效率方法

    少用in操作(效率极差),尽量用表关联代替 select要指定列,不要*(*会读入所有数据,而指定列则只提取涉及的列,减少io) 尽量有where(减少读取量),where操作列尽量有索引(加快查询) ...

  4. [转载]要提高SQL查询效率where语句条件的先后次序应如何写

    出处:https://www.cnblogs.com/exe19/p/5786806.html 我们要做到不但会写SQL,还要做到写出性能优良的SQL语句. (1)选择最有效率的表名顺序(只在基于规则 ...

  5. IT之快速提高效率的方法与思考

    前言 文章也没什么很高深的问题,大概花个5分钟能看完.是一些大家都知道的道理,作为提醒与总结. 关于提高方面的内容,一般都有个人的方法,但大致都一致.可分为几个步骤. 框架.工具使用相关 使用框架.工 ...

  6. Atitit.研发管理--提升效率--软件开发方法DSM总结o99

    Atitit.研发管理--提升效率--软件开发方法DSM总结o99 1. 什么是DSM? 1 2. DSM使用的语言DSL 2 3. 模型的优点 2 4. DSM 跟与MDA区别 2 5. MDA的实 ...

  7. 批处理文件(.bat)并行Arcpy脚本提高效率的思路

    Arcpy提供数据处理的方便接口,但一个Arcpy脚本通常只运行于一个核上.现在电脑通常是多核乃至多处理器,如果能将任务分解为可同时进行的若干任务,便可通过并行充分利用电脑性能. 折腾了python并 ...

  8. Oracle多表连接,提高效率,性能优化 (转)

    执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要几十表了. ...

  9. SQL Server 百万级数据提高查询速度的方法

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...

随机推荐

  1. EC读书笔记系列之6:条款11 在operator=中处理自我赋值

    记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...

  2. 在MyEclipse环境下添加MySql数据库

    首先最好在添加的时候,确保你的数据库处于打开状态:其次,要按照jdbc:mysql://[host:port],[host:port].../[database]把url写对:然后,需要添加mysql ...

  3. 监听enter事件

    document.onkeydown=keyDownSearch; function keyDownSearch(e) { // 兼容FF和IE和Opera var theEvent = e || w ...

  4. php数组分页类

    <?php class ArrayPage{ public $totalPage;//全部页数 public $lists;//每页显示数目 public $arr = array();//分页 ...

  5. Generative Learning algorithms

    "generative algorithm models how the data was generated in order to categorize a signal. It ask ...

  6. (C)学生成绩管理系统

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h&g ...

  7. php正则表达式图谱

    php 正则表达式分类图:

  8. 如何在 静态编译的QT 5.5.1 中 使用数据库插件连接 ODBC(调用静态插件)

    前段时间由于工作的关系,需要编写一个将数据插入到 Sql server 2012 的桌面软件. 由于之前使用的是MFC,偶然间接触到了Qt后,被它的简洁惊艳到了,于是便毅然而然的转投到了Qt的怀抱,哈 ...

  9. java把函数作为参数传递

    public class Tool { public void a()// /方法a { System.out.print("tool.a()..."); } public voi ...

  10. Debug程序无法运行解决

    说明:文章内容部分参考网络上的解决思路. 在没有安装Microsoft Visual Studio的系统上,Debug版本无法正常运行.这是由于缺少vs运行时库引起的. 以vs2005为例.开发机用v ...