Nutch 1.3 源码分析 8 LinkDb

1. 运行命令 bin/nutch invertlinks

帮助参数说明:
view plain
  1. Usage: LinkDb <linkdb> (-dir <segmentsDir> | <seg1> <seg2> ...) [-force] [-noNormalize] [-noFilter]  
  2.     linkdb  output LinkDb to create or update  
  3.     -dir segmentsDir    parent directory of several segments, OR  
  4.     seg1 seg2 ...    list of segment directories  
  5.     -force  force update even if LinkDb appears to be locked (CAUTION advised)  
  6.     -noNormalize    don't normalize link URLs  
  7.     -noFilter   don't apply URLFilters to link URLs  

本地的运行结果为:
view plain
  1. lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ bin/nutch invertlinks db/linkdb/ db/segments/20110822105243/   
  2.     LinkDb: starting at 2011-08-29 09:21:36  
  3.     LinkDb: linkdb: db/linkdb  
  4.     LinkDb: URL normalize: true  
  5.     LinkDb: URL filter: true  
  6.     LinkDb: adding segment: db/segments/20110822105243            // 加入新的segment库  
  7.     LinkDb: merging with existing linkdb: db/linkdb               // 与原因的库进行合并  
  8.     LinkDb: finished at 2011-08-29 09:21:40, elapsed: 00:00:03  

2. LinkDb主要源代码分析

在LinkDb主要是调用一个invert方法,这个方法做了两件事,
+ 分析新输入的segment目录,产生新的反向链接库
+ 把新产生的反向链接库与原来的库进行合并


2.1 分析新输入的segment目录,主要代码如下:

view plain
  1. // 新建立一个MP任务  
  2.     JobConf job = LinkDb.createJob(getConf(), linkDb, normalize, filter);  
  3.     // 添加目录到输入路径,这里可能有多个输入路径, parse_data  
  4.     for (int i = 0; i < segments.length; i++) {  
  5.       if (LOG.isInfoEnabled()) {  
  6.         LOG.info("LinkDb: adding segment: " + segments[i]);  
  7.       }  
  8.       FileInputFormat.addInputPath(job, new Path(segments[i], ParseData.DIR_NAME));      
  9.     }  
  10.     // 提交MP任务  
  11.     try {  
  12.       JobClient.runJob(job);  
  13.     } catch (IOException e) {  
  14.       LockUtil.removeLockFile(fs, lock);  
  15.       throw e;  
  16.     }  

下面来看一下createJob都做了些什么:
view plain
  1. private static JobConf createJob(Configuration config, Path linkDb, boolean normalize, boolean filter) {  
  2.         // 新成一个临时的目录  
  3.     Path newnewLinkDb =  
  4.       new Path("linkdb-" +  
  5.                Integer.toString(new Random().nextInt(Integer.MAX_VALUE)));  
  6.   
  7.   
  8.     JobConf job = new NutchJob(config);  
  9.     job.setJobName("linkdb " + linkDb);  
  10.   
  11.   
  12.     // 设置输出格式  
  13.     job.setInputFormat(SequenceFileInputFormat.class);  
  14.   
  15.   
  16.     // 配置Map,Combiner,Reducer方法  
  17.     job.setMapperClass(LinkDb.class);  
  18.     job.setCombinerClass(LinkDbMerger.class);  
  19.       
  20.     // 如果配置了过滤或者规格化,并且没有找到老的linkdb目录,好就以filter和normalize进行配置  
  21.     // if we don't run the mergeJob, perform normalization/filtering now  
  22.     if (normalize || filter) {  
  23.       try {  
  24.         FileSystem fs = FileSystem.get(config);  
  25.         if (!fs.exists(linkDb)) {  
  26.           job.setBoolean(LinkDbFilter.URL_FILTERING, filter);  
  27.           job.setBoolean(LinkDbFilter.URL_NORMALIZING, normalize);  
  28.         }  
  29.       } catch (Exception e) {  
  30.         LOG.warn("LinkDb createJob: " + e);  
  31.       }  
  32.     }  
  33.     job.setReducerClass(LinkDbMerger.class);  
  34.   
  35.   
  36.     // 配置MP输出路径  
  37.     FileOutputFormat.setOutputPath(job, newLinkDb);  
  38.     // 配置输出格式  
  39.     job.setOutputFormat(MapFileOutputFormat.class);  
  40.     // 对map输出使用压缩,以减少Reducer的输入压力  
  41.     job.setBoolean("mapred.output.compress", true);  
  42.     // 配置<key,value>的输出类型  
  43.     job.setOutputKeyClass(Text.class);  
  44.     job.setOutputValueClass(Inlinks.class);  
  45.   
  46.   
  47.     return job;  
  48.   }  

  下面来看一下LinkDb中的map做了些什么,这个方法主要是从toUrl=>fromUrl建立一个对应关系,这个有点像倒排索引中的TermId=>DocId
  而LinkDbMerger这个类实现了reducer接口,主要是收集指定个数的同一个toUrl的fromUrl,这个指定的个数可能通过设置db.max.inlinks来设定。 


  2.2 把新产生的反向链接库与老的库进行合并,主要代码如下:

view plain
  1. if (fs.exists(currentLinkDb)) {   // 如果存在老的反向链接库,就进行合并  
  2.    if (LOG.isInfoEnabled()) {  
  3.      LOG.info("LinkDb: merging with existing linkdb: " + linkDb);  
  4.    }  
  5.    // try to merge  
  6. //   
  7.    Path newLinkDb = FileOutputFormat.getOutputPath(job);  
  8.    job = LinkDbMerger.createMergeJob(getConf(), linkDb, normalize, filter);  
  9. // 加入输入路径  
  10.    FileInputFormat.addInputPath(job, currentLinkDb);  
  11.    FileInputFormat.addInputPath(job, newLinkDb);  
  12.    try {  
  13.      JobClient.runJob(job);  
  14.    } catch (IOException e) {  
  15.      LockUtil.removeLockFile(fs, lock);  
  16.      fs.delete(newLinkDb, true);  
  17.      throw e;  
  18.    }  
  19.    fs.delete(newLinkDb, true);  
  20.  }  
  21.  LinkDb.install(job, linkDb); // 安装新生成的反向链接库  

我们再看一下createMergeJob做了些什么:
view plain
  1. public static JobConf createMergeJob(Configuration config, Path linkDb, boolean normalize, boolean filter) {  
  2.      // 生成一个临时目录  
  3.    Path newnewLinkDb =  
  4.      new Path("linkdb-merge-" +   
  5.               Integer.toString(new Random().nextInt(Integer.MAX_VALUE)));  
  6.   
  7.   
  8.    JobConf job = new NutchJob(config);  
  9.    job.setJobName("linkdb merge " + linkDb);  
  10. // 配置个输出格式  
  11.    job.setInputFormat(SequenceFileInputFormat.class);  
  12.   
  13.   
  14. // 配置Map与Reducer方法,这里的Reducer方法与上面的一样,用于对相同key(toUrl)的values进行聚合  
  15. // 然后输出指定个数的value,而这里的LinkDbFilter应该是对key与value所对应的url进行过滤与正规化  
  16.    job.setMapperClass(LinkDbFilter.class);  
  17.    job.setBoolean(LinkDbFilter.URL_NORMALIZING, normalize);  
  18.    job.setBoolean(LinkDbFilter.URL_FILTERING, filter);  
  19.    job.setReducerClass(LinkDbMerger.class);  
  20.   
  21.   
  22. // 配置输出路径  
  23.    FileOutputFormat.setOutputPath(job, newLinkDb);  
  24.    job.setOutputFormat(MapFileOutputFormat.class);  
  25.    job.setBoolean("mapred.output.compress", true);  
  26.    job.setOutputKeyClass(Text.class);  
  27.    job.setOutputValueClass(Inlinks.class);  
  28.   
  29.   
  30.    return job;  
  31.  }  

  3. bin/nutch readlinkdb 分析

主要是用于下载linkdb的内容到指定的目录,帮助如下:

     
view plain
  1. Usage: LinkDbReader <linkdb> {-dump <out_dir> | -url <url>)  
  2.     -dump <out_dir>   dump whole link db to a text file in <out_dir>  
  3.     -url <url>    print information about <url> to System.out  

下面是本机运行的结果:
view plain
  1. lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ bin/nutch readlinkdb db/linkdb/ -dump output2  
  2.     LinkDb dump: starting at 2011-08-29 09:54:08  
  3.     LinkDb dump: db: db/linkdb/  
  4.     LinkDb dump: finished at 2011-08-29 09:54:09, elapsed: 00:00:01  

下面是输出output2目录中文件的部分内容,可以看到,这里一个<key,value>对,key是toUrl,value是fromUrl
view plain
  1. lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ head output2/part-00000   
  2. http://baike.baidu.com/ Inlinks:  
  3.         fromUrl: http://www.baidu.com/ anchor: 百科  
  4.   
  5. http://hi.baidu.com/    Inlinks:  
  6.         fromUrl: http://www.baidu.com/ anchor: 空间  
  7.   
  8. http://hi.baidu.com/baidu/  Inlinks:  
  9.         fromUrl: http://www.baidu.com/ anchor:   
  10.   
  11. http://home.baidu.com/  Inlinks:  

这个readlinkdb也是用了一个MP任务,输入格式为SequenceFileInputFormat,输出格式为TextOutput,Map-Reducer都是用的默认的。


   4. bin/nutch mergelinkdb 分析

主要是用来合并个不同的linkdb数据库的

view plain
  1.     Usage: LinkDbMerger <output_linkdb> <linkdb1> [<linkdb2> <linkdb3> ...] [-normalize] [-filter]  
  2. output_linkdb   output LinkDb  
  3. linkdb1 ... input LinkDb-s (single input LinkDb is ok)  
  4. -normalize  use URLNormalizer on both fromUrls and toUrls in linkdb(s) (usually not needed)  
  5. -filter use URLFilters on both fromUrls and toUrls in linkdb(s)  

其实这里的合并就是调用上面分析的LinkDbMerger中的createMergeJob方法

   5. 总结
这里主要是对于parse_data目录中分析出来的外链接进行反向链接的计算,在下面计算链接分数的时候会用到这些反向链接。

你可能感兴趣的:(数据库,Debian,filter,任务,output,代码分析)