c httpclient抓取网页(修改heritrix的默认抓取策略()的抓取算法)

优采云 发布时间: 2022-03-28 02:11

  c httpclient抓取网页(修改heritrix的默认抓取策略()的抓取算法)

  一种。首先修改heritrix的默认爬取策略

  Heritrix默认的抓取策略是HostnameQueueAssignmentPolicy,该策略以hostname为key,所以一个域名下的所有连接都会放在同一个线程中,这样会导致抓取时一般只有一个线程运行(一般我们抓取特定 网站 上的内容)。这种方法可以很大程度上解决广域网中取信息时队列的键值问题。但是,单个 网站 网络抓取存在很大问题。以新浪的新闻页面为例,大部分的URL来自新浪网站内部,所以如果使用HostnameQueueAssignmentPolicy,会造成很长的队列。在 Heritrix 中,当线程从队列中获取 URL 链接时,它总是从队列的头部获取第一个链接。在那之后,从中获取链接的队列将进入阻塞状态,直到链接被处理。之后,它将从阻塞状态中恢复。如果使用HostnameQueueAssignmentPolicy策略来处理抓取一个网站的内容的情况,很有可能只有一个线程在工作,而所有其他线程都在等待。这是因为拥有绝大多数 URL 链接的队列将几乎永远被阻塞,因此其他线程根本无法获取 URL,在这种情况下,抓取工作将进入一种类似睡眠的状态。而所有其他线程都在等待。这是因为拥有绝大多数 URL 链接的队列将几乎永远被阻塞,因此其他线程根本无法获取 URL,在这种情况下,抓取工作将进入一种类似睡眠的状态。而所有其他线程都在等待。这是因为拥有绝大多数 URL 链接的队列将几乎永远被阻塞,因此其他线程根本无法获取 URL,在这种情况下,抓取工作将进入一种类似睡眠的状态。

  因此,我们需要改变Heritrix的爬取策略,即改变key的生成方式。我们需要使用这个键有效地将所有 URL 散列到不同的队列中,最终减少所有队列长度的方差。,在这种情况下,可以保证工作线程的最大效率。我们需要继承QueueAssignmentPolicy类,重写getClassKey()方法。getClassKey 方法的参数是一个链接对象,ELF Hash 算法可以通过这个链接对象返回一个值,并将其平均分配到各个队列中。更多线程爬取同域名下的网页,爬取速度会大大提高。

  ELFHash算法是对字符串进行哈希运算,巧妙地计算出字符的ASCII码值,可以将字符串在哈希表中分布更均匀。

  1、以下是ELFHash算法实现的抓取策略:

  package org.archive.crawler.frontier;

import java.util.logging.Level;

import java.util.logging.Logger;

import org.apache.commons.httpclient.URIException;

import org.archive.crawler.datamodel.CandidateURI;

import org.archive.crawler.framework.CrawlController;

import org.archive.net.UURI;

import org.archive.net.UURIFactory;

public class ELFHashQueueAssignmentPolicy extends QueueAssignmentPolicy {

private static final Logger logger = Logger.getLogger(ELFHashQueueAssignmentPolicy.class.getName());

/**

* When neat host-based class-key fails us

*/

private static String DEFAULT_CLASS_KEY = "default...";

private static final String DNS = "dns";

public String getClassKey(CrawlController controller, CandidateURI cauri) {

String scheme = cauri.getUURI().getScheme();

String candidate = null;

try {

if (scheme.equals(DNS)){

if (cauri.getVia() != null) {

// Special handling for DNS: treat as being

// of the same class as the triggering URI.

// When a URI includes a port, this ensures

// the DNS lookup goes atop the host:port

// queue that triggered it, rather than

// some other host queue

UURI viaUuri = UURIFactory.getInstance(cauri.flattenVia());

candidate = viaUuri.getAuthorityMinusUserinfo();

// adopt scheme of triggering URI

scheme = viaUuri.getScheme();

} else {

candidate= cauri.getUURI().getReferencedHost();

}

} else {

// 注释掉原来的

// candidate = cauri.getUURI().getAuthorityMinusUserinfo();

// 使用ELFHash算法

String uri = cauri.getUURI().toString();

long hash = ELFHash(uri);

candidate = Long.toString(hash % 100); // 取模 100,Heritrix默认开100个线程,对应100个不同的URI处理队列

}

if(candidate == null || candidate.length() == 0) {

candidate = DEFAULT_CLASS_KEY;

}

} catch (URIException e) {

logger.log(Level.INFO,

"unable to extract class key; using default", e);

candidate = DEFAULT_CLASS_KEY;

}

if (scheme != null && scheme.equals(UURIFactory.HTTPS)) {

// If https and no port specified, add default https port to

// distinguish https from http server without a port.

if (!candidate.matches(".+:[0-9]+")) {

candidate += UURIFactory.HTTPS_PORT;

}

}

// Ensure classKeys are safe as filenames on NTFS

return candidate.replace(':','#');

}

public long ELFHash(String str) {

long hash = 0;

long x = 0;

for (int i = 0; i < str.length(); i++) {

hash = (hash > 24);

hash &= ~x;

}

}

return (hash & 0x7FFFFFFF);

}

}

  2、在 org.archive.crawler.frontier.AbstractFrontier 类中查找“HostnameQueueAssignmentPolicy”关键字,大约第 293 行,注释掉更改,然后添加我们的 ELFHashQueueAssignmentPolicy,如下(蓝色字体行):

   // Read the list of permissible choices from heritrix.properties.

// Its a list of space- or comma-separated values.

String queueStr = System.getProperty(AbstractFrontier.class.getName() +

"." + ATTR_QUEUE_ASSIGNMENT_POLICY,

// HostnameQueueAssignmentPolicy.class.getName() + " " +

ELFHashQueueAssignmentPolicy.class.getName() + " " +

IPQueueAssignmentPolicy.class.getName() + " " +

BucketQueueAssignmentPolicy.class.getName() + " " +

SurtAuthorityQueueAssignmentPolicy.class.getName() + " " +

TopmostAssignedSurtQueueAssignmentPolicy.class.getName());

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

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

  3、修改heritrix.properties文件中的配置,在文件中查找“HostnameQueueAssignmentPolicy”关键字,15左右两行9、160,复制后将这两行注释掉,粘贴到下面, 将这两行中的“HostnameQueueAssignmentPolicy”替换为“ELFHashQueueAssignmentPolicy”,如下(蓝色字体):

  #org.archive.crawler.frontier.AbstractFrontier.queue-assignment-policy = 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.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.AbstractFrontier.queue-assignment-policy = org.archive.crawler.frontier.ELFHashQueueAssignmentPolicy org.archive.crawler.frontier.IPQueueAssignmentPolicy org.archive.crawler.frontier.BucketQueueAssignmentPolicy org.archive.crawler.frontier.SurtAuthorityQueueAssignmentPolicy org.archive.crawler.frontier.TopmostAssignedSurtQueueAssignmentPolicy

org.archive.crawler.frontier.ELFHashQueueAssignmentPolicy org.archive.crawler.frontier.IPQueueAssignmentPolicy org.archive.crawler.frontier.BucketQueueAssignmentPolicy org.archive.crawler.frontier.SurtAuthorityQueueAssignmentPolicy org.archive.crawler.frontier.TopmostAssignedSurtQueueAssignmentPolicy

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

  下面我们分别使用这两种抓取策略来创建抓取任务并做个对比:

  下图是使用 HostnameQueueAssignmentPolicy 抓取策略创建的任务的状态图:

  

  下图是使用 ELFHashQueueAssignmentPolicy 抓取策略创建的任务的状态图:

  

  从上面两张图可以看出,同时在活跃线程数和fetches总大小上,ELFHashQueueAssignmentPolicy远高于HostnameQueueAssignmentPolicy。

  注意:当使用 ELFHashQueueAssignmentPolicy 爬取策略时,爬取可能会停止。检查任务的 crawl.log 日志。URL后跟“robots.txt”,如:“”。这是因为Heritrix是一个完整的遵守“robots.txt”协议的网络爬虫,如果一个网站声明了他们不想被机器人访问的部分文件,Heritrix不会爬取那些内容。可以去掉robots.txt的限制,应该不会出现这种现象。

  湾。取消rebots.txt的限制。

  关于rebots.txt协议的取消,可以参考另一篇文章文章:

  C。抓取指定网页内容

  Heritrix的Extractors用于解析当前服务器返回的内容,提取页面中的URL,放入提取队列。因为它会爬取网页中的所有链接,但是有些链接不是我们想要的,比如图片链接、pdf文档等,这些链接需要过滤掉,我们可以创建自己的Extractor来爬取特定的网页内容。如下,是一个自定义的抓取搜狐新闻的Extractor:

<p>package org.archive.crawler.extractor;

import java.io.IOException;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.archive.crawler.datamodel.CrawlURI;

import org.archive.io.ReplayCharSequence;

import org.archive.util.HttpRecorder;

public class ExtractorSohu extends Extractor {

private static final long serialVersionUID = -7914995152462902519L;

public ExtractorSohu(String name, String description) {

super(name, description);

}

public ExtractorSohu(String name) {

super(name, "sohu news extractor");

}

// http://news.sohu.com/20131020/n388534488.shtml

private static final String A_HERF = "

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线