Apache Nutch 1.3 学习笔记八(LinkDb)
这里主要是分析一下org.apache.nutch.crawl.LinkDb,它主要是用计算反向链接。
1. 运行命令 bin/nutch invertlinks
帮助参数说明:
-
Usage: LinkDb <linkdb> (-dir <segmentsDir> | <seg1> <seg2> ...) [-force] [-noNormalize] [-noFilter]
-
linkdb output LinkDb to create or update
-
-dir segmentsDir parent directory of several segments, OR
-
seg1 seg2 ... list of segment directories
-
-force force update even if LinkDb appears to be locked (CAUTION advised)
-
-noNormalize don't normalize link URLs
-
-noFilter don't apply URLFilters to link URLs
本地的运行结果为:
-
lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ bin/nutch invertlinks db/linkdb/ db/segments/20110822105243/
-
LinkDb: starting at 2011-08-29 09:21:36
-
LinkDb: linkdb: db/linkdb
-
LinkDb: URL normalize: true
-
LinkDb: URL filter: true
-
LinkDb: adding segment: db/segments/20110822105243 // 加入新的segment库
-
LinkDb: merging with existing linkdb: db/linkdb // 与原因的库进行合并
-
LinkDb: finished at 2011-08-29 09:21:40, elapsed: 00:00:03
2. LinkDb主要源代码分析
在LinkDb主要是调用一个invert方法,这个方法做了两件事,
+ 分析新输入的segment目录,产生新的反向链接库
+ 把新产生的反向链接库与原来的库进行合并
2.1 分析新输入的segment目录,主要代码如下:
-
// 新建立一个MP任务
-
JobConf job = LinkDb.createJob(getConf(), linkDb, normalize, filter);
-
// 添加目录到输入路径,这里可能有多个输入路径, parse_data
-
for (int i = 0; i < segments.length; i++) {
-
if (LOG.isInfoEnabled()) {
-
LOG.info("LinkDb: adding segment: " + segments[i]);
-
}
-
FileInputFormat.addInputPath(job, new Path(segments[i], ParseData.DIR_NAME));
-
}
-
// 提交MP任务
-
try {
-
JobClient.runJob(job);
-
} catch (IOException e) {
-
LockUtil.removeLockFile(fs, lock);
-
throw e;
-
}
下面来看一下createJob都做了些什么:
-
private static JobConf createJob(Configuration config, Path linkDb, boolean normalize, boolean filter) {
-
// 新成一个临时的目录
-
Path newnewLinkDb =
-
new Path("linkdb-" +
-
Integer.toString(new Random().nextInt(Integer.MAX_VALUE)));
-
-
-
JobConf job = new NutchJob(config);
-
job.setJobName("linkdb " + linkDb);
-
-
-
// 设置输出格式
-
job.setInputFormat(SequenceFileInputFormat.class);
-
-
-
// 配置Map,Combiner,Reducer方法
-
job.setMapperClass(LinkDb.class);
-
job.setCombinerClass(LinkDbMerger.class);
-
-
// 如果配置了过滤或者规格化,并且没有找到老的linkdb目录,好就以filter和normalize进行配置
-
// if we don't run the mergeJob, perform normalization/filtering now
-
if (normalize || filter) {
-
try {
-
FileSystem fs = FileSystem.get(config);
-
if (!fs.exists(linkDb)) {
-
job.setBoolean(LinkDbFilter.URL_FILTERING, filter);
-
job.setBoolean(LinkDbFilter.URL_NORMALIZING, normalize);
-
}
-
} catch (Exception e) {
-
LOG.warn("LinkDb createJob: " + e);
-
}
-
}
-
job.setReducerClass(LinkDbMerger.class);
-
-
-
// 配置MP输出路径
-
FileOutputFormat.setOutputPath(job, newLinkDb);
-
// 配置输出格式
-
job.setOutputFormat(MapFileOutputFormat.class);
-
// 对map输出使用压缩,以减少Reducer的输入压力
-
job.setBoolean("mapred.output.compress", true);
-
// 配置<key,value>的输出类型
-
job.setOutputKeyClass(Text.class);
-
job.setOutputValueClass(Inlinks.class);
-
-
-
return job;
-
}
下面来看一下LinkDb中的map做了些什么,这个方法主要是从toUrl=>fromUrl建立一个对应关系,这个有点像倒排索引中的TermId=>DocId
而LinkDbMerger这个类实现了reducer接口,主要是收集指定个数的同一个toUrl的fromUrl,这个指定的个数可能通过设置db.max.inlinks来设定。
2.2 把新产生的反向链接库与老的库进行合并,主要代码如下:
-
if (fs.exists(currentLinkDb)) { // 如果存在老的反向链接库,就进行合并
-
if (LOG.isInfoEnabled()) {
-
LOG.info("LinkDb: merging with existing linkdb: " + linkDb);
-
}
-
// try to merge
-
//
-
Path newLinkDb = FileOutputFormat.getOutputPath(job);
-
job = LinkDbMerger.createMergeJob(getConf(), linkDb, normalize, filter);
-
// 加入输入路径
-
FileInputFormat.addInputPath(job, currentLinkDb);
-
FileInputFormat.addInputPath(job, newLinkDb);
-
try {
-
JobClient.runJob(job);
-
} catch (IOException e) {
-
LockUtil.removeLockFile(fs, lock);
-
fs.delete(newLinkDb, true);
-
throw e;
-
}
-
fs.delete(newLinkDb, true);
-
}
-
LinkDb.install(job, linkDb); // 安装新生成的反向链接库
我们再看一下createMergeJob做了些什么:
-
public static JobConf createMergeJob(Configuration config, Path linkDb, boolean normalize, boolean filter) {
-
// 生成一个临时目录
-
Path newnewLinkDb =
-
new Path("linkdb-merge-" +
-
Integer.toString(new Random().nextInt(Integer.MAX_VALUE)));
-
-
-
JobConf job = new NutchJob(config);
-
job.setJobName("linkdb merge " + linkDb);
-
// 配置个输出格式
-
job.setInputFormat(SequenceFileInputFormat.class);
-
-
-
// 配置Map与Reducer方法,这里的Reducer方法与上面的一样,用于对相同key(toUrl)的values进行聚合
-
// 然后输出指定个数的value,而这里的LinkDbFilter应该是对key与value所对应的url进行过滤与正规化
-
job.setMapperClass(LinkDbFilter.class);
-
job.setBoolean(LinkDbFilter.URL_NORMALIZING, normalize);
-
job.setBoolean(LinkDbFilter.URL_FILTERING, filter);
-
job.setReducerClass(LinkDbMerger.class);
-
-
-
// 配置输出路径
-
FileOutputFormat.setOutputPath(job, newLinkDb);
-
job.setOutputFormat(MapFileOutputFormat.class);
-
job.setBoolean("mapred.output.compress", true);
-
job.setOutputKeyClass(Text.class);
-
job.setOutputValueClass(Inlinks.class);
-
-
-
return job;
-
}
3. bin/nutch readlinkdb 分析
主要是用于下载linkdb的内容到指定的目录,帮助如下:
-
Usage: LinkDbReader <linkdb> {-dump <out_dir> | -url <url>)
-
-dump <out_dir> dump whole link db to a text file in <out_dir>
-
-url <url> print information about <url> to System.out
下面是本机运行的结果:
-
lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ bin/nutch readlinkdb db/linkdb/ -dump output2
-
LinkDb dump: starting at 2011-08-29 09:54:08
-
LinkDb dump: db: db/linkdb/
-
LinkDb dump: finished at 2011-08-29 09:54:09, elapsed: 00:00:01
下面是输出output2目录中文件的部分内容,可以看到,这里一个<key,value>对,key是toUrl,value是fromUrl
-
lemo@debian:~/Workspace/java/Apache/Nutch/nutch-1.3$ head output2/part-00000
-
http://baike.baidu.com/ Inlinks:
-
fromUrl: http://www.baidu.com/ anchor: 百科
-
-
http://hi.baidu.com/ Inlinks:
-
fromUrl: http://www.baidu.com/ anchor: 空间
-
-
http://hi.baidu.com/baidu/ Inlinks:
-
fromUrl: http://www.baidu.com/ anchor:
-
-
http://home.baidu.com/ Inlinks:
这个readlinkdb也是用了一个MP任务,输入格式为SequenceFileInputFormat,输出格式为TextOutput,Map-Reducer都是用的默认的。
4. bin/nutch mergelinkdb 分析
主要是用来合并个不同的linkdb数据库的
-
Usage: LinkDbMerger <output_linkdb> <linkdb1> [<linkdb2> <linkdb3> ...] [-normalize] [-filter]
-
output_linkdb output LinkDb
-
linkdb1 ... input LinkDb-s (single input LinkDb is ok)
-
-normalize use URLNormalizer on both fromUrls and toUrls in linkdb(s) (usually not needed)
-
-filter use URLFilters on both fromUrls and toUrls in linkdb(s)
其实这里的合并就是调用上面分析的LinkDbMerger中的createMergeJob方法
5. 总结
这里主要是对于parse_data目录中分析出来的外链接进行反向链接的计算,在下面计算链接分数的时候会用到这些反向链接。
作者:http://blog.csdn.net/amuseme_lu
相关文章阅读及免费下载:
《Apache Nutch 1.3 学习笔记三(Inject)》
《Apache Nutch 1.3 学习笔记三(Inject CrawlDB Reader)》
《Apache Nutch 1.3 学习笔记四(Generate)》
《Apache Nutch 1.3 学习笔记四(SegmentReader分析)》
《Apache Nutch 1.3 学习笔记五(FetchThread)》
《Apache Nutch 1.3 学习笔记五(Fetcher流程)》
《Apache Nutch 1.3 学习笔记六(ParseSegment)》
《Apache Nutch 1.3 学习笔记七(CrawlDb - updatedb)》
《Apache Nutch 1.3 学习笔记八(LinkDb)》
《Apache Nutch 1.3 学习笔记九(SolrIndexer)》
《Apache Nutch 1.3 学习笔记十(Ntuch 插件机制简单介绍)》
《Apache Nutch 1.3 学习笔记十(插件扩展)》
《Apache Nutch 1.3 学习笔记十(插件机制分析)》
《Apache Nutch 1.3 学习笔记十一(页面评分机制 OPIC)》
《Apache Nutch 1.3 学习笔记十一(页面评分机制 LinkRank 介绍)》
《Apache Nutch 1.3 学习笔记十二(Nutch 2.0 的主要变化)》