
(1)BdbFrontier链接工厂,initQueue()初始化等待队列
public class BdbFrontier extends WorkQueueFrontier implements Serializable { /** 所有待抓取的链接*/ protected transient BdbMultipleWorkQueues pendingUris; //初始化pendingUris,父类为抽象方法 protected void initQueue() throws IOException { try { this.pendingUris = createMultipleWorkQueues(); } catch(DatabaseException e) { throw (IOException)new IOException(e.getMessage()).initCause(e); } } private BdbMultipleWorkQueues createMultipleWorkQueues() throws DatabaseException { return new BdbMultipleWorkQueues(this.controller.getBdbEnvironment(), this.controller.getBdbEnvironment().getClassCatalog(), this.controller.isCheckpointRecover()); } protected BdbMultipleWorkQueues getWorkQueues() { return pendingUris; }
(2)next():为处理线程提供一个链接.Heritrix的所有处理线程(ToeThread)都是通过调用该方法获取链接的.
就是WorkQueueFrontier的next()方法。
*说明:WorkQueueFrontier的next方法实际是调用WorkQueue的peek()方法,WorkQueue的peek()方法又由BdbWorkQueue的peekItem()来实现,BdbWorkQueue的peekItem()方法又调用BdbFrontier的getWorkQueues()方法拿到BdbMultipleWorkQueues队列也就是等待队列,在调用BdbMultipleWorkQueues的get()方法调用getNextNearestItem()方法从等待队列中拿出链接并加入正在处理队列。
public CrawlURI next() throws InterruptedException, EndedException { while (true) { // loop left only by explicit return or exception long now = System.currentTimeMillis(); // Do common checks for pause, terminate, bandwidth-hold preNext(now); synchronized(readyClassQueues) { int activationsNeeded = targetSizeForReadyQueues() - readyClassQueues.size(); while(activationsNeeded > 0 && !inactiveQueues.isEmpty()) { activateInactiveQueue(); activationsNeeded--; } } WorkQueue readyQ = null; Object key = readyClassQueues.poll(DEFAULT_WAIT,TimeUnit.MILLISECONDS); if (key != null) { readyQ = (WorkQueue)this.allQueues.get(key); } if (readyQ != null) { while(true) { // loop left by explicit return or break on empty CrawlURI curi = null; synchronized(readyQ) { /**取出一个URL,最终从子类BdbFrontier的 * pendingUris中(即等待队列中)取出一个链接 */ curi = readyQ.peek(this); if (curi != null) { // check if curi belongs in different queue String currentQueueKey = getClassKey(curi); if (currentQueueKey.equals(curi.getClassKey())) { // curi was in right queue, emit noteAboutToEmit(curi, readyQ); //加入正在处理队列中 inProcessQueues.add(readyQ); return curi; //返回 } // URI's assigned queue has changed since it // was queued (eg because its IP has become // known). Requeue to new queue. curi.setClassKey(currentQueueKey); readyQ.dequeue(this);//出队列 decrementQueuedCount(1); curi.setHolderKey(null); // curi will be requeued to true queue after lock // on readyQ is released, to prevent deadlock } else { // readyQ is empty and ready: it's exhausted // release held status, allowing any subsequent // enqueues to again put queue in ready readyQ.clearHeld(); break; } } if(curi!=null) { // complete the requeuing begun earlier sendToQueue(curi); } } } else { // ReadyQ key wasn't in all queues: unexpected if (key != null) { logger.severe("Key "+ key + " in readyClassQueues but not allQueues"); } } if(shouldTerminate) { // skip subsequent steps if already on last legs throw new EndedException("shouldTerminate is true"); } if(inProcessQueues.size()==0) { // Nothing was ready or in progress or imminent to wake; ensure // any piled-up pending-scheduled URIs are considered this.alreadyIncluded.requestFlush(); } } }
(3)schedule(CandidateURI caURI):将caURI放入等待队列,其实就是BdbMultipleWorkQueues管理的
Berkeley Database数据库,用于存放等待的链接。
//将URL加入待处理队列 public void schedule(CandidateURI caUri) { // Canonicalization may set forceFetch flag. See // #canonicalization(CandidateURI) javadoc for circumstance. String canon = canonicalize(caUri); if (caUri.forceFetch()) { alreadyIncluded.addForce(canon, caUri); } else { alreadyIncluded.add(canon, caUri); } }
(4)BdbUriUniqFilter:实际上是一个过滤器,它用来检查一个要进入等待队列的链接是否已经被抓取过.
//添加URL入等待队列 protected boolean setAdd(CharSequence uri) { DatabaseEntry key = new DatabaseEntry(); LongBinding.longToEntry(createKey(uri), key); long started = 0; OperationStatus status = null; try { if (logger.isLoggable(Level.INFO)) { started = System.currentTimeMillis(); } //添加到数据库 status = alreadySeen.putNoOverwrite(null, key, ZERO_LENGTH_ENTRY); if (logger.isLoggable(Level.INFO)) { aggregatedLookupTime += (System.currentTimeMillis() - started); } } catch (DatabaseException e) { logger.severe(e.getMessage()); } if (status == OperationStatus.SUCCESS) { count++; if (logger.isLoggable(Level.INFO)) { final int logAt = 10000; if (count > 0 && ((count % logAt) == 0)) { logger.info("Average lookup " + (aggregatedLookupTime / logAt) + "ms."); aggregatedLookupTime = 0; } } } //如果存在,返回false if(status == OperationStatus.KEYEXIST) { return false; // not added } else { return true; } }
(5)finished(CrawlURI cURI):完成一个已处理的链接.
---------------------------------------------------------------------------------------------------------------
补充:


- 大小: 88.8 KB

- 大小: 170.1 KB
分享到:
相关推荐
- **扩展Crawler Frontier**:Heritrix的工作核心是Crawler Frontier,它是待抓取URL的管理器。你需要扩展这个组件,加入PageRank计算逻辑,以决定优先级。 - **URL排序策略**:根据PageRank值对URL队列进行排序,...
4. **Politeness**:这是Heritrix遵循的一种网络礼貌原则,即在抓取过程中,尊重网站的Robots协议,避免过于频繁的请求,以免对目标服务器造成过大的负担。这通过设置延迟时间和重试策略来实现。 Heritrix的灵活性...
#### 三、Heritrix的学习路径建议 1. **基础理解**:首先了解Heritrix的基本概念和架构设计。 2. **核心包分析**:深入研究上述提到的核心包,理解其内部工作原理和交互机制。 3. **实践应用**:基于Heritrix构建...
CrawlController从Frontier获取URL,传递给线程池(ToePool)中的ToeThread处理。 Frontier(边界控制器)主要确定下一个将被处理的URL,负责访问的均衡处理,避免对某一Web服务器造成太大的压力。Frontier保存着爬虫的...
在压缩包`internetarchive-heritrix3-d6d1092`中,可能包含了Heritrix3的源代码、编译好的JAR文件、示例配置文件以及相关文档。开发者可以通过这些资源了解Heritrix3的内部工作原理,对其进行二次开发或定制化配置,...
Heritrix是一款开源的网络爬虫工具,其官方开发文档《Heritrix developer manual》旨在为用户和贡献者提供学习Heritrix网络爬虫内部机制和可能向核心软件贡献或添加新模块的起点。文档中提到了获取和构建Heritrix的...
Heritrix 是一款开源的、可扩展的、网络级别的、具有归档质量的网页抓取工具,它由 Internet Archive 开发。Heritrix 的用户手册提供了如何创建、配置和运行抓取任务的详细说明,适用于那些对网页抓取至少有基本了解...
### Heritrix源码分析(十一):Heritrix中的URL——CandidateURI和CrawlURI #### 一、概述 Heritrix是一款开源的网络爬虫工具,它主要用于归档和备份网页数据。Heritrix的设计非常灵活且可扩展性强,能够支持多种...
以下是Heritrix在电子信息垂直搜索平台中的核心知识点: 1. **多线程机制**:Heritrix利用多线程技术提高网页抓取效率。其中,ToePool是一个标准的线程库,用于管理所有的工作线程,确保爬虫能够并行处理多个网页...
为了提高爬取效率,Heritrix的Profiles设置中可以调整“max-delay-ms”、“min-delay-ms”、“max-retries”和“retry-delay-seconds”的数值,这些参数影响了Heritrix在处理URL时的等待时间和重试策略。同时,通过...
- 选择URI Frontier,选择`org.archive.crawler.frontier.BdbFrontier`。 - 选择Pre Processors,依次选择`org.archive.crawler.prefetch.Preselector`和`org.archive.crawler.prefetch.PreconditionEnforcer`。 ...
14. **浏览Bean**:Bean是Heritrix中的数据结构,用于表示爬取过程中的不同状态和数据。 15. **配置文件和配置作业**:阐述如何创建、编辑配置文件(Profile),以及如何根据特定需求定制爬取行为。 16. **处理链*...
11. `org.archive.crawler.framework`:Heritrix的框架包,定义了核心类如CrawlController(爬虫控制器)和Frontier(调度器),是整个系统架构的基础。 12. `org.archive.crawler.framework.exceptions`:框架异常...
在本案例中,"heritrix-1.4.4 源代码(eclipse可执行)" 表示这个压缩包包含了Heritrix 1.4.4版本的所有源码,这些源码是为Eclipse IDE准备的,可以直接在Eclipse环境下编译和运行。Eclipse是一款强大的Java集成开发...
实现Heritrix的增量抓取功能,可以在Processing Chains中添加额外的组件,如: 1. **HttpContentDigest**:在Extractor Processing Chain开头,用于生成网页内容的摘要,以便比较新旧版本的差异。 2. **...
【Heritrix框架详解】 Heritrix是一款由Java编写的开源Web爬虫系统,专用于获取网站的深度复制,确保内容的完整性和精确性。它的最大特点在于其强大的可扩展性,允许开发者根据需求自由选择或扩展不同的组件,实现...