本博客属原创文章,欢迎转载!转载请务必注明出处: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,下面贴上代码:

  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.InputStreamReader;
  8. import java.io.UnsupportedEncodingException;
  9. import java.sql.Connection;
  10. import java.sql.ResultSet;
  11. import java.sql.SQLException;
  12. import java.sql.Statement;
  13. import org.archive.crawler.frontier.RecoveryJournal;
  14. public class UrlToRecoverUtil {
  15. /**
  16. * 从文件中导入URl到recover.gz以便URL不再被抓取
  17. *
  18. * @param sourceFilePath        URL来源文件
  19. * @param sourceFileEncoding    URL来源文件的编码
  20. * @param recoverGzPath         要写到的recover.gz文件目录
  21. * @param recoverGzFileName     recover.gz文件名,可以为空
  22. * @return
  23. */
  24. public static boolean urlToRecoverUtilByFile(String sourceFilePath,String sourceFileEncoding,String recoverGzDir,String recoverGzFileName){
  25. boolean result=false;
  26. InputStream is=null;
  27. InputStreamReader isr=null;
  28. BufferedReader br=null;
  29. File sourceFile=null;
  30. String line=null;
  31. RecoveryJournal recover = null;
  32. try {
  33. sourceFile=new File(sourceFilePath);
  34. //recover.gz文件为空则采用默认名字
  35. if(recoverGzFileName==null||recoverGzFileName.equals("")){
  36. recoverGzFileName="recover.gz";
  37. }
  38. recover=new RecoveryJournal(recoverGzDir,recoverGzFileName);//构造recover.gz对象
  39. //读取文件内容
  40. is=new FileInputStream(sourceFile);
  41. isr=new InputStreamReader(is,sourceFileEncoding);
  42. br=new BufferedReader(isr);
  43. //一行一行写入recover.gz文件
  44. while((line=br.readLine().trim())!=null){
  45. if(!line.equals("")){
  46. recover.writeLine(RecoveryJournal.F_SUCCESS, line);
  47. }
  48. }
  49. result=true;
  50. } catch (FileNotFoundException e) {
  51. e.printStackTrace();
  52. } catch (UnsupportedEncodingException e) {
  53. e.printStackTrace();
  54. } catch (IOException e) {
  55. e.printStackTrace();
  56. }finally{
  57. try {
  58. if(recover!=null){
  59. recover.close();
  60. }
  61. if(br!=null){
  62. br.close();
  63. }
  64. if(isr!=null){
  65. isr.close();
  66. }
  67. if(is!=null){
  68. is.close();
  69. }
  70. } catch (IOException e) {
  71. e.printStackTrace();
  72. }
  73. }
  74. return result;
  75. }
  76. /**
  77. * 从ResultSet结果集中获取URL导入到recover.gz以便URl不再被抓取
  78. *
  79. * @param rs                ResultSet结果集
  80. * @param filedName         ResultSet结果集中要获取URL对应的字段名
  81. * @param recoverGzDir      要写到的recover.gz文件目录
  82. * @param recoverGzFileName recover.gz文件名,可以为空
  83. * @return
  84. */
  85. public static boolean urlToRecoverUtilByResultSet(ResultSet rs,String filedName,String recoverGzDir,String recoverGzFileName){
  86. boolean result=false;
  87. String line=null;
  88. RecoveryJournal recover = null;
  89. try {
  90. if(recoverGzFileName==null||recoverGzFileName.equals("")){
  91. recoverGzFileName="recover.gz";
  92. }
  93. recover=new RecoveryJournal(recoverGzDir,recoverGzFileName);
  94. if(rs!=null){
  95. while(rs.next()){
  96. line=rs.getString(filedName).trim();
  97. if(!line.equals("")){
  98. recover.writeLine(RecoveryJournal.F_SUCCESS, line);
  99. }
  100. }
  101. result=true;
  102. }
  103. } catch (SQLException e) {
  104. e.printStackTrace();
  105. } catch (IOException e) {
  106. e.printStackTrace();
  107. }finally{
  108. try {
  109. if(rs!=null){
  110. rs.close();
  111. }
  112. if(recover!=null){
  113. recover.close();
  114. }
  115. } catch (SQLException e) {
  116. e.printStackTrace();
  117. }
  118. }
  119. return result;
  120. }
  121. /**
  122. * @param args
  123. */
  124. public static void main(String[] args) {
  125. /*
  126. * 示例,从结果集中写入URL到recover.gz
  127. */
  128. Connection con=null;
  129. Statement stmt=null;
  130. ResultSet rs=null;
  131. String sql="SELECT CLASSIFY_INFO_URL FROM CLASSIFY_INFO";
  132. boolean result=false;
  133. try {
  134. con=DatabaseUtil.getConnection_Mysql_CrawlServer_Local();//获取Connection
  135. stmt=con.createStatement();
  136. rs=stmt.executeQuery(sql);
  137. result=urlToRecoverUtilByResultSet(rs,"CLASSIFY_INFO_URL","D:/HeritrixRecover/",null);
  138. System.out.println("从结果集中导入URL到recover.gz文件:"+(result?"成功!":"失败!"));
  139. } catch (SQLException e) {
  140. // TODO Auto-generated catch block
  141. e.printStackTrace();
  142. }finally{
  143. DatabaseUtil.closeConnection(con, stmt, rs);//关闭Connection、Statement、ResultSet
  144. }
  145. }
  146. }

这个工具类其实主要也只是生成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的更多相关文章

  1. Heritrix源码分析(十四) 如何让Heritrix不间断的抓取(转)

    欢迎加入Heritrix群(QQ):109148319,10447185 , Lucene/Solr群(QQ) :  118972724 本博客已迁移到本人独立博客: http://www.yun5u ...

  2. Heritrix源码分析(十四)

    近段时间在搞定Lucene的一些问题,所以Heritrix源码分析暂时告一段落.今天下午在群里有同学提到了Heritrix异常终止的问题以及让Heritrix不停的抓取(就是抓完一遍后载入种子继续抓取 ...

  3. 手机自动化测试:appium源码分析之bootstrap十二

    手机自动化测试:appium源码分析之bootstrap十二   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...

  4. HDFS源码分析之UnderReplicatedBlocks(二)

    UnderReplicatedBlocks还提供了一个数据块迭代器BlockIterator,用于遍历其中的数据块.它是UnderReplicatedBlocks的内部类,有三个成员变量,如下: // ...

  5. 【集合框架】JDK1.8源码分析之LinkedHashMap(二)

    一.前言 前面我们已经分析了HashMap的源码,已经知道了HashMap可以用在哪种场合,如果这样一种情形,我们需要按照元素插入的顺序来访问元素,此时,LinkedHashMap就派上用场了,它保存 ...

  6. 【JUC】JDK1.8源码分析之AbstractQueuedSynchronizer(二)

    一.前言 在锁框架中,AbstractQueuedSynchronizer抽象类可以毫不夸张的说,占据着核心地位,它提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.所以很有必 ...

  7. 【JUC】JDK1.8源码分析之ConcurrentSkipListMap(二)

    一.前言 最近在做项目的同时也在修复之前项目的一些Bug,所以忙得没有时间看源代码,今天都完成得差不多了,所以又开始源码分析之路,也着笔记录下ConcurrentSkipListMap的源码的分析过程 ...

  8. 【Zookeeper】源码分析之网络通信(二)

    一.前言 前面介绍了ServerCnxn,下面开始学习NIOServerCnxn. 二.NIOServerCnxn源码分析 2.1 类的继承关系 public class NIOServerCnxn ...

  9. 【Zookeeper】源码分析之服务器(二)

    一.前言 前面阐述了服务器的总体框架,下面来分析服务器的所有父类ZooKeeperServer. 二.ZooKeeperServer源码分析 2.1 类的继承关系 public class ZooKe ...

随机推荐

  1. JavaScript. The core.

    Read this article in: Japanese, German (version 2), Arabic, Russian, French, Chinese. An object A pr ...

  2. 聊聊并发(八)——Fork/Join框架介绍

      作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...

  3. JavaWeb项目开发案例精粹-第6章报价管理系统-05Action层

    0. <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &quo ...

  4. Win8.1安装VirtualSVN Server发生service visualSVN Server failed to start解决办法

    Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for mo ...

  5. DP-母函数

    DP---母函数 先由钱币兑换问题开始 http://acm.hdu.edu.cn/showproblem.php?pid=1284 Problem Description 在一个国家仅有1分,2分, ...

  6. JVM加载class文件的原理

    当Java编译器编译好.class文件之后,我们需要使用JVM来运行这个class文件.那么最开始的工作就是要把字节码从磁盘输入到内存中,这个过程我们叫做[加载 ].加载完成之后,我们就可以进行一系列 ...

  7. CentOS7安装配置Apache HTTP Server

    RPM安装httpd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # yum -yinstall http ...

  8. Oracle ->> 行转列, 列转行

    除了Pivot和Unpivot这两个函数,还有像CASE WHEN + 聚合函数像MAX,SUM这类的来完成.今天发现Oracle下居然有这样一个和SQL SERVER 2012以后新增的新函数叫II ...

  9. code manager tools git的使用;

    git的使用 一.下载及安装: 1.下载:https://github.com 2.安装: 二.常用命令: 查看.添加.提交.删除.找回,重置修改文件 git help< command> ...

  10. ExtJS4之Ext.MessageBox的各种用法

    1. Ext.Msg.alert(String title,String msg)[Ext.MsssageBox.alert(Sting title,Sting msg,fn)]与javascript ...