Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL
本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/644396
本博客已迁移到本人独立博客: http://www.yun5u.com/
欢迎加入Heritrix群(QQ):109148319,10447185 , Lucene/Solr群(QQ) : 118972724
前面说过Heritrix可以在某个抓取基础上(这里假设为A)继续抓取,因为Heritrix对每一个URL都会有相应的日志处理,同时还有checkpoint(备份中心)。所以只要通过A上的日志就可以完全按照该基础A继续抓取,不会重复抓取任何A抓过的任何东西,也会继续抓取A没有抓过的URL。做到这个有两种方法,一种是针对Web启动的,还有一种是针对我上次写的不通过Web启动的方式(启动方式见博客:Heritrix源码分析(五) 如何让Heritrix在Ecplise等IDE下编程启动).
1)下面介绍这两种启动方式,第一种,通过Web启动:
进入页面,选择:Jobs->Base on a recovery->然后再选择你要二次抓取的Job中的recover-log->然后再点击按钮Submit Job。之后回到Console页面,点击Start。之后就开始再你想要的基础上抓取了。你可以进入这个新建的抓取JOB下的logs目录,发现里面有个recover.gz大小跟你想要二次抓取JOB中的recover.gz大小一般大。以及你去查看该job下的order.xml中的<string name="recover-path"></string>中间的值发现就是你要二次抓取job下recover.gz的绝对目录
2)不通过Web方式启动:
这个相对简单,只要修改order.xml中<string name="recover-path">D:/recover.gz</string>,中间的值就是你想二次抓取的JOB中logs目录下recover.gz的绝对路径。
同时最好更新一下值为:
<boolean name="checkpoint-copy-bdbje-logs">true</boolean>
<boolean name="recover-retain-failures">false</boolean>
<boolean name="recover-scope-includes">false</boolean>
<boolean name="recover-scope-enqueues">false</boolean>
至于为什么要这样设置,请参考我关于order.xml介绍的博客:Heritrix源码分析(二) 配置文件order.xml介绍
同时可能你已经知道某些URL不需要抓取,比如从数据库导出来的,而这些URL你的Heritrix并没有处理过。所以这些外部的URL就无法通过以上两种办法导入Heritrix了。这里我写了个工具类,有两种方式,一种是你将URL都放在文件中,然后通过这个工具类从这个文件中读取这些URL(必须一行一个URL),导入到Heritrix中。还有一种方法是针对数据库的,你只要提供相应的ResultSet以及该URL对应数据库的字段名,也可以导入Heritrix,下面贴上代码:
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.UnsupportedEncodingException;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import org.archive.crawler.frontier.RecoveryJournal;
- public class UrlToRecoverUtil {
- /**
- * 从文件中导入URl到recover.gz以便URL不再被抓取
- *
- * @param sourceFilePath URL来源文件
- * @param sourceFileEncoding URL来源文件的编码
- * @param recoverGzPath 要写到的recover.gz文件目录
- * @param recoverGzFileName recover.gz文件名,可以为空
- * @return
- */
- public static boolean urlToRecoverUtilByFile(String sourceFilePath,String sourceFileEncoding,String recoverGzDir,String recoverGzFileName){
- boolean result=false;
- InputStream is=null;
- InputStreamReader isr=null;
- BufferedReader br=null;
- File sourceFile=null;
- String line=null;
- RecoveryJournal recover = null;
- try {
- sourceFile=new File(sourceFilePath);
- //recover.gz文件为空则采用默认名字
- if(recoverGzFileName==null||recoverGzFileName.equals("")){
- recoverGzFileName="recover.gz";
- }
- recover=new RecoveryJournal(recoverGzDir,recoverGzFileName);//构造recover.gz对象
- //读取文件内容
- is=new FileInputStream(sourceFile);
- isr=new InputStreamReader(is,sourceFileEncoding);
- br=new BufferedReader(isr);
- //一行一行写入recover.gz文件
- while((line=br.readLine().trim())!=null){
- if(!line.equals("")){
- recover.writeLine(RecoveryJournal.F_SUCCESS, line);
- }
- }
- result=true;
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- try {
- if(recover!=null){
- recover.close();
- }
- if(br!=null){
- br.close();
- }
- if(isr!=null){
- isr.close();
- }
- if(is!=null){
- is.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return result;
- }
- /**
- * 从ResultSet结果集中获取URL导入到recover.gz以便URl不再被抓取
- *
- * @param rs ResultSet结果集
- * @param filedName ResultSet结果集中要获取URL对应的字段名
- * @param recoverGzDir 要写到的recover.gz文件目录
- * @param recoverGzFileName recover.gz文件名,可以为空
- * @return
- */
- public static boolean urlToRecoverUtilByResultSet(ResultSet rs,String filedName,String recoverGzDir,String recoverGzFileName){
- boolean result=false;
- String line=null;
- RecoveryJournal recover = null;
- try {
- if(recoverGzFileName==null||recoverGzFileName.equals("")){
- recoverGzFileName="recover.gz";
- }
- recover=new RecoveryJournal(recoverGzDir,recoverGzFileName);
- if(rs!=null){
- while(rs.next()){
- line=rs.getString(filedName).trim();
- if(!line.equals("")){
- recover.writeLine(RecoveryJournal.F_SUCCESS, line);
- }
- }
- result=true;
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- try {
- if(rs!=null){
- rs.close();
- }
- if(recover!=null){
- recover.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- return result;
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- /*
- * 示例,从结果集中写入URL到recover.gz
- */
- Connection con=null;
- Statement stmt=null;
- ResultSet rs=null;
- String sql="SELECT CLASSIFY_INFO_URL FROM CLASSIFY_INFO";
- boolean result=false;
- try {
- con=DatabaseUtil.getConnection_Mysql_CrawlServer_Local();//获取Connection
- stmt=con.createStatement();
- rs=stmt.executeQuery(sql);
- result=urlToRecoverUtilByResultSet(rs,"CLASSIFY_INFO_URL","D:/HeritrixRecover/",null);
- System.out.println("从结果集中导入URL到recover.gz文件:"+(result?"成功!":"失败!"));
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }finally{
- DatabaseUtil.closeConnection(con, stmt, rs);//关闭Connection、Statement、ResultSet
- }
- }
- }
这个工具类其实主要也只是生成recover.gz文件。如果你采用Web方式启动,你只要找到一个你抓取过的JOB,然后用这个生成的recover.gz目录覆盖你找到job下logs目录中的recover.gz即可。而如果你采用非Web启动就更简单了,只要将order.xml中<string name="recover-path">D:/recover.gz</string>中的值改成你生成recover.gz绝对路径即可!
Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL的更多相关文章
- Heritrix源码分析(十四) 如何让Heritrix不间断的抓取(转)
欢迎加入Heritrix群(QQ):109148319,10447185 , Lucene/Solr群(QQ) : 118972724 本博客已迁移到本人独立博客: http://www.yun5u ...
- Heritrix源码分析(十四)
近段时间在搞定Lucene的一些问题,所以Heritrix源码分析暂时告一段落.今天下午在群里有同学提到了Heritrix异常终止的问题以及让Heritrix不停的抓取(就是抓完一遍后载入种子继续抓取 ...
- 手机自动化测试:appium源码分析之bootstrap十二
手机自动化测试:appium源码分析之bootstrap十二 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- HDFS源码分析之UnderReplicatedBlocks(二)
UnderReplicatedBlocks还提供了一个数据块迭代器BlockIterator,用于遍历其中的数据块.它是UnderReplicatedBlocks的内部类,有三个成员变量,如下: // ...
- 【集合框架】JDK1.8源码分析之LinkedHashMap(二)
一.前言 前面我们已经分析了HashMap的源码,已经知道了HashMap可以用在哪种场合,如果这样一种情形,我们需要按照元素插入的顺序来访问元素,此时,LinkedHashMap就派上用场了,它保存 ...
- 【JUC】JDK1.8源码分析之AbstractQueuedSynchronizer(二)
一.前言 在锁框架中,AbstractQueuedSynchronizer抽象类可以毫不夸张的说,占据着核心地位,它提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.所以很有必 ...
- 【JUC】JDK1.8源码分析之ConcurrentSkipListMap(二)
一.前言 最近在做项目的同时也在修复之前项目的一些Bug,所以忙得没有时间看源代码,今天都完成得差不多了,所以又开始源码分析之路,也着笔记录下ConcurrentSkipListMap的源码的分析过程 ...
- 【Zookeeper】源码分析之网络通信(二)
一.前言 前面介绍了ServerCnxn,下面开始学习NIOServerCnxn. 二.NIOServerCnxn源码分析 2.1 类的继承关系 public class NIOServerCnxn ...
- 【Zookeeper】源码分析之服务器(二)
一.前言 前面阐述了服务器的总体框架,下面来分析服务器的所有父类ZooKeeperServer. 二.ZooKeeperServer源码分析 2.1 类的继承关系 public class ZooKe ...
随机推荐
- Win32应用程序中文支持
Settings--Editor---Encoding改为Windows 936 main.cpp中#include "locale.h" winmain中增加一行: setloc ...
- WCF分布式开发步步为赢(5)服务契约与操作重载
继上一节WCF分布式开发步步为赢系列的(4):WCF服务可靠性传输配置与编程开发,本节我们继续学习WCF分布式开发步步为赢的第(5)节:服务契约与操作重载.这里我们首先讲解OOP面向对象的编程中方法重 ...
- 机器学习之逻辑回归(Logistic Regression)
1. Classification 这篇文章我们来讨论分类问题(classification problems),也就是说你想预测的变量 y 是一个离散的值.我们会使用逻辑回归算法来解决分类问题. 之 ...
- node-debug 三法三例之node debugger + node inspector
大家对nodejs调试应该都比较头疼,至少我这个不用IDE写js的人很头疼这个,其实node的生态圈非常好 有非常好的工具和非常潮的开发方式 这里总结了3法3例,希望能对大家有所帮助 文档地址 ht ...
- Javascript 数组循环遍历之forEach
1. js 数组循环遍历. 数组循环变量,最先想到的就是 for(var i=0;i<count;i++)这样的方式了. 除此之外,也可以使用较简便的forEach 方式 2. forE ...
- badboy 之 查看回放结果
在运行脚本时,Badboy提供了Summary功能方便我们监控回放结果状态,如下Summary view: 以下表格对运行情况的各个维度进行解释: 统计点 描述 Played 运行或回放脚本的次数 S ...
- iOS 深入Objective-C的动态特性
深入Objective-C的动态特性 Objective-C具有相当多的动态特性,基本的,也是经常被提到和用到的有动态类型(Dynamic typing),动态绑定(Dynamic binding)和 ...
- Git教程之安装配置(1)
1.Git是什么? Git是目前世界上最先进的分布式版本控制系统. 2.SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...
- MyBatis学习总结_11_MyBatis动态Sql语句
MyBatis中对数据库的操作,有时要带一些条件,因此动态SQL语句非常有必要,下面就主要来讲讲几个常用的动态SQL语句的语法 MyBatis中用于实现动态SQL的元素主要有: if choose(w ...
- Android实现透明的颜色效果
android Button或者ImageButton背景透明状态设置 设置Button或ImageButton的背景为透明或者半透明 半透明< Button android:backgroun ...