欢迎加入Heritrix群(QQ):109148319
近段时间在搞定Lucene的一些问题,所以Heritrix源码分析暂时告一段落。今天下午在群里有同学提到了Heritrix异常终止的问题以及让Heritrix不停的抓取(就是抓完一遍后载入种子继续抓取,目前他是写个定时器,定时检查Heritrix是否停止,如果停止了则重新初始化Heritrix,让Heritrix重新抓取,但这个方法就不可避免的会导致抓取重复URl,除非从recover.gz导入)。我想这2个问题都可以用我下面这个方法,但对于Heritrix异常终止的问题这个方法也只是治标不治本,要改动的地方蛮多,涉及到Heritrix的设计以及结构,不是一时可以完成。下面就介绍原理以及方法:
1.原理:
Heritrix的自然停止(就是非人为以及不可抗力因素,如Web UI界面出发停止命令)的依据是判断调度器里面是否还有URL可抓取,如果没有则当前线程退出,如果是单线程抓取的话,则也意味着Heritrix的结束。如果是多线程抓取的话,则每个线程在获取不到URL的时候都会置不在活动状态,当最后一个活动状态线程也获取不到URL的时候则Heritrix也会进入自然停止。所以我们可以在判断Heritrix是否还有URL可抓取的时候做一些处理,比较简单的方法就是重新载入种子以及唤醒所有抓取线程。但由于处在多线程抓取模式中,每个线程都会判断,如此会导致多次载入种子,造成不必要的浪费,所以这里也要做一些同步控制。不要导致过分载入种子,而是每抓完一次则重新载入种子。
2.方法:
修改org.archive.crawler.frontier.WorkQueueFrontier中的public CrawlURI next()方法,这里也对该方法做一些介绍,具体请看源码注释,改成如下,红色部分为改动部分:
/** * 从调度中心获取下一个要抓取的URL * */ public CrawlURI next() throws InterruptedException, EndedException { while (true) {//一直不停的循环,直到遇到异常或终止 // 郭芸修改,用于当队列里没有可抓取的URL的时候去获取种子继续 synchronized (this) { if (this.controller.getFrontier().isEmpty()) { //如果没有可抓取的URL loadSeeds(); //重新载入种子 this.controller.getToePool().notifyAll(); //唤醒所有抓取线程 } } long now = System.currentTimeMillis();//开始获取时间 // 检查是否有暂停命令、结束命令以及宽带控制,这里会导致Heritrix结束 preNext(now); /* * 允许最多一个线程去填充准备队列(readyClassQueues) */ if (readyFiller.tryAcquire()) {// 表示没有线程去使用当前变量,当前类1次只允许1个线程同时使用 try { // 空闲队列数=目标队列数-准备队列数 int activationsNeeded = targetSizeForReadyQueues() - readyClassQueues.size(); // 如果空闲队列数大于0,并且不在活动状态的队列数不是空的,则表示需要将不在活动状态的队列转移到准备队列 while (activationsNeeded > 0 && !inactiveQueues.isEmpty()) { activateInactiveQueue();//将不在活动状态队列的URL转移一定数目到活动状态队列 activationsNeeded--; } } finally { readyFiller.release();// 必须释放,这样下次才可以继续使用 } } WorkQueue readyQ = null;//准备工作队列 // 获取并移除此准备队列表示的队列的头部(即准备队列的第一个元素)如果该队列没有可用元素,则等待指定的时间,这里是1000毫秒也就是1秒 Object key = readyClassQueues.poll(DEFAULT_WAIT,TimeUnit.MILLISECONDS);// 获得classKey,然后再通过classKey去获得队列 if (key != null) { readyQ = (WorkQueue) this.allQueues.get(key);// 获得工作队列WorkQueue } if (readyQ != null) { while (true) { // 一直循环,直到抛出异常或终止 CrawlURI curi = null; synchronized (readyQ) {//锁定准备队列,让其他线程无法获取,避免脏读 curi = readyQ.peek(this); // 从数据库pendingUrls中获取CrawlURI if (curi != null) { // 检查该curi是否属于不同的队列 String currentQueueKey = getClassKey(curi); if (currentQueueKey.equals(curi.getClassKey())) { //在正确的队列,排放它 noteAboutToEmit(curi, readyQ); inProcessQueues.add(readyQ);// 加入已处理队列 return curi; } curi.setClassKey(currentQueueKey); readyQ.dequeue(this); //从调度器中删除刚获取到的URL decrementQueuedCount(1); //计数 curi.setHolderKey(null); } else { readyQ.clearHeld(); break; } } if (curi != null) { sendToQueue(curi); //将获取到的URL发送到它该属于的队列 } } } else { if (key != null) { logger.severe("Key " + key + " in readyClassQueues but not allQueues"); } } //如果该强烈退出,则抛异常结束循环 if (shouldTerminate) { throw new EndedException("shouldTerminate is true"); } //如果没有处理中的队列,则刷新该队列 if (inProcessQueues.size() == 0) { this.alreadyIncluded.requestFlush(); } } }
更多技术文章、感悟、分享、勾搭,请用微信扫描:
相关推荐
heritrix学习源码和资料
heritrix抓取指南heritrix抓取指南 heritrix抓取指南
Heritrix的文件结构分析 各个类说明 配置文件order_xml介绍....
Lucene 2.0+Heritrix 源码 csdn 开发自己的搜索引擎——Lucene 2.0+Heritrix
自己学习网络爬虫时知识所学习的资料,希望可以和大家分享,并能对大家有所帮助,希望能共同进步。
对heritrix抓取的操作和扩展 里面有MirrorWriterProcessor扩展的类文件修改
heritrix1.14.4的源码包,包含heritrix1.14.4.zip和heritrix1.14.4-src.zip。heritrix是一种开源的网络爬虫,用于爬去互联网中的网页。如何配置和使用heritrix爬虫,请移步:...
Heritrix1.14.4安装配置使用包,其中包括源码包。 具体使用方法可参考:http://blog.csdn.net/baalhuo/article/details/52189425
heritrix3.2源码包 https://github.com/xiamizy/heritrix-package 下载编译后的文件
heritrix1.14.4源码+项目
Heritrix+Lucene+Dwr 搜索引擎框架包 多次开发中使用的 据对可用
Lucene Heritrix 搜索 Lucene Heritrix csdn
从网上找得应该是中文Heritrix源码最详细的说明了。折腾了好久,没有把网页打成chm,只能打个exe用用。
开发自己的搜索引擎lucene+heritrix(第2版)(ch13-ch15源码)
Heritrix User Manual https://webarchive.jira.com/wiki/display/Heritrix/Heritrix3 Heritrix3(或简称H3)指Heritrix的3.0发布。 目前官方的Heritrix 3.0.0版已经发布(2009年12月)。 后续的发行H3将是3.0.1...
heritrix-1.14.4爬虫框架及源码
heritrix正确完整的配置heritrix正确完整的配置heritrix正确完整的配置heritrix正确完整的配置heritrix正确完整的配置
Heritrix是按多线程方式抓取的爬虫,主线程把任务分配给Teo线程(处理线程),每个Teo线程每次处理一个URL。Teo线程对每个URL执行一遍URL处理器链。URL处理器链包括如下5个处理步骤。整个流程都在图2.1中。 (1)预取链...
自己学习网络爬虫时知识所学习的资料,希望可以和大家分享,并能对大家有所帮助,希望能共同进步。
在/Heritrix1/src/org/archive/crawler/Heritrix.java启动之后,访问https://localhost:8089登录admin密码admin直接用