注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Nutch 1.0 源代码分析[9] LinkDb  

2010-03-24 18:45:02|  分类: Nutch |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

         再接下来Crawl中一个重要的类是LinkDb

linkDbTool.invert(linkDb, segments, true, true, false);

         linkDbTool拆成两部分:

Path currentLinkDb = new Path(linkDb, CURRENT_NAME);

JobConf job = LinkDb.createJob(getConf(), linkDb, normalize, filter);

for (int i = 0; i < segments.length; i++) {

    FileInputFormat.addInputPath(job, new Path(segments[i],

           ParseData.DIR_NAME));

}

try {

    JobClient.runJob(job);

}

         将每个segment中的parse_data作为输入加入。

private static JobConf createJob(Configuration config, Path linkDb,

       boolean normalize, boolean filter) {

    JobConf job = new NutchJob(config);

 

    job.setInputFormat(SequenceFileInputFormat.class);

 

    job.setMapperClass(LinkDb.class);

    job.setCombinerClass(LinkDbMerger.class);

    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;

}

         这里Mapper类为LinkDb,而Reducer类为LinkDbMerger

         LinkDb类中的map函数为:

public void map(Text key, ParseData parseData,

       OutputCollector<Text, Inlinks> output, Reporter reporter)

       throws IOException {

    String fromUrl = key.toString();

    String fromHost = getHost(fromUrl);

    if (urlNormalizers != null) {

       try {

           fromUrl = urlNormalizers.normalize(fromUrl,

                  URLNormalizers.SCOPE_LINKDB); // normalize the url

       }

    }

    if (fromUrl != null && urlFilters != null) {

       try {

           fromUrl = urlFilters.filter(fromUrl); // filter the url

       }

    }

    if (fromUrl == null)

       return; // discard all outlinks

         得到原URL的主机名,对原URL进行规范化,过滤。

    Outlink[] outlinks = parseData.getOutlinks();

    Inlinks inlinks = new Inlinks();

    for (int i = 0; i < outlinks.length; i++) {

       Outlink outlink = outlinks[i];

       String toUrl = outlink.getToUrl();

 

       if (ignoreInternalLinks) {

           String toHost = getHost(toUrl);

           if (toHost == null || toHost.equals(fromHost)) {

              continue; // skip it

           }

       }

       if (urlNormalizers != null) {

           try {

              toUrl = urlNormalizers.normalize(toUrl,

                     URLNormalizers.SCOPE_LINKDB); // normalize the url

           }

       }

       if (toUrl != null && urlFilters != null) {

           try {

              toUrl = urlFilters.filter(toUrl); // filter the url

           }

       }

       if (toUrl == null)

           continue;

       inlinks.clear();

       String anchor = outlink.getAnchor(); // truncate long anchors

       if (anchor.length() > maxAnchorLength) {

           anchor = anchor.substring(0, maxAnchorLength);

       }

       inlinks.add(new Inlink(fromUrl, anchor));// collect inverted link

       output.collect(new Text(toUrl), inlinks);

    }

}

         得到所有的外链,如果这个外链和原URL有同一主机名,并且在忽略内部链接时,就不管了,接下来,对这个URL也进行规范化,过滤。再得到外链相应的锚点,将这个放入inlinks中,最后output得到的是key是外链URLvalue是原URL和锚点合起来的一个对象。

         CombinerReducer类是LinkDbMerger,它的reduce函数如下:

public void reduce(Text key, Iterator<Inlinks> values,

       OutputCollector<Text, Inlinks> output, Reporter reporter)

       throws IOException {

    Inlinks result = new Inlinks();

 

    while (values.hasNext()) {

       Inlinks inlinks = values.next();

 

       int end = Math.min(maxInlinks - result.size(), inlinks.size());

       Iterator<Inlink> it = inlinks.iterator();

       int i = 0;

       while (it.hasNext() && i++ < end) {

           result.add(it.next());

       }

    }

    if (result.size() == 0)

       return;

    output.collect(key, result);

 

}

         每次将一个URL的外部链接合到一起,最多为maxInlinks

         再接下来是invert函数的下一部分:

if (fs.exists(currentLinkDb)) {

    // 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);

    }

    fs.delete(newLinkDb, true);

}

         如果已经有一个linkdb了,那么试着合并,即将刚才产生的linkdb和以前的linkdb合并,createMergeJob的代码如下:

public static JobConf createMergeJob(Configuration config, Path linkDb,

       boolean normalize, boolean filter) {

    JobConf job = new NutchJob(config);

 

    job.setInputFormat(SequenceFileInputFormat.class);

 

    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;

}

         这里Reducer类仍然是LinkDbMerger,而Mapper类是LinkDbFilter,它的map函数为:

public void map(Text key, Inlinks value,

       OutputCollector<Text, Inlinks> output, Reporter reporter)

       throws IOException {

    String url = key.toString();

    Inlinks result = new Inlinks();

 

    Iterator<Inlink> it = value.iterator();

    String fromUrl = null;

    while (it.hasNext()) {

       Inlink inlink = it.next();

       fromUrl = inlink.getFromUrl();

      

       if (fromUrl != null) {

           result.add(new Inlink(fromUrl, inlink.getAnchor()));

       }

    }

    if (result.size() > 0) { // don't collect empty inlinks

       newKey.set(url);

       output.collect(newKey, result);

    }

}

         这里又相当于是一个LinkDbMerger的反过程,把一个个<url,outlinks>又拆开,目的是进行下一步的reduce合并,这里add是没有关系的,因为Inlinks的成员变量inlinksHashSet<Inlink>

 

 

 

 

 

 

  评论这张
 
阅读(1711)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017