nutch源码分析——invertlink

2021SC@SDUSC

LinkDb::main

ToolRunner的run函数最终调用LinkDb的run函数

public static void main(String[] args) throws Exception {
    int res = ToolRunner.run(NutchConfiguration.create(), new LinkDb(), args);
    System.exit(res);
  }

LinkDb::run

 public int run(String[] args) throws Exception {
    invert(db, segs.toArray(new Path[segs.size()]), normalize, filter, force);
    return 0;
  }

  public void invert(Path linkDb, Path[] segments, boolean normalize,
      boolean filter, boolean force) throws IOException {
    JobConf job = LinkDb.createJob(getConf(), linkDb, normalize, filter);
    Path lock = new Path(linkDb, LOCK_NAME);
    FileSystem fs = FileSystem.get(getConf());
    LockUtil.createLockFile(fs, lock, force);
    Path currentLinkDb = new Path(linkDb, CURRENT_NAME);

    for (int i = 0; i < segments.length; i++) {
      FileInputFormat.addInputPath(job, new Path(segments[i],
          ParseData.DIR_NAME));
    }
    JobClient.runJob(job);
    if (fs.exists(currentLinkDb)) {
      Path newLinkDb = FileOutputFormat.getOutputPath(job);
      job = LinkDbMerger.createMergeJob(getConf(), linkDb, normalize, filter);
      FileInputFormat.addInputPath(job, currentLinkDb);
      FileInputFormat.addInputPath(job, newLinkDb);
      JobClient.runJob(job);
      fs.delete(newLinkDb, true);
    }
    LinkDb.install(job, linkDb);
  }

  private static JobConf createJob(Configuration config, Path linkDb,
      boolean normalize, boolean filter) {
    Path newLinkDb = new Path("linkdb-"
        + Integer.toString(new Random().nextInt(Integer.MAX_VALUE)));

    JobConf job = new NutchJob(config);
    job.setJobName("linkdb " + linkDb);
    job.setInputFormat(SequenceFileInputFormat.class);
    job.setMapperClass(LinkDb.class);
    job.setCombinerClass(LinkDbMerger.class);

    if (normalize || filter) {
      FileSystem fs = FileSystem.get(config);
      if (!fs.exists(linkDb)) {
        job.setBoolean(LinkDbFilter.URL_FILTERING, filter);
        job.setBoolean(LinkDbFilter.URL_NORMALIZING, normalize);
      }
    }
    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;
  }

  public static JobConf createMergeJob(Configuration config, Path linkDb,
      boolean normalize, boolean filter) {
    Path newLinkDb = 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);

    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;

invert函数创建了两个hadoop的Job,第一个Job设置输入为crawl/segments/*/下的parse_data目录,Mapper函数为LinkDb的map函数,Reducer为LinkDbMerger,Combiner为LinkDbMerger,该Job的作用是把parse_data中记录的url记录连接进行反向,存入临时目录newLinkDb中,所谓反向,比方说parse_data目录中记录的url链接为A(Key)->B(Value)、A(Key)->C(Value)、B(Key)->C(Value),经过反向处理后,输出的链接为B(Key)->A(value) 、C(Key)->A(value)、C(Key)->B(value),即正向链接记录的信息是“一个url地址链接到哪些url地址”,反向链接记录的信息是“有多少url地址链接到这个url地址”。
invert的第二个Job通过LinkDbMerger的createMergeJob函数创建,该Job的作用是将第一个Job输出的临时文件夹newLinkDb,与crawl/linkdb/current,即之前的反向信息合并,输出到另一个临时文件夹中。
最后执行LinkDb的install函数更新信息,LinkDb的install函数和前几章分析的install函数类似,都将第二个Job输出的临时文件夹命名为current、将原来的current文件夹命名为old,将原来的old文件夹删除。

先来看第一个Job。

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);
    fromUrl = urlNormalizers
        .normalize(fromUrl, URLNormalizers.SCOPE_LINKDB);
    fromUrl = urlFilters.filter(fromUrl);

    Outlink[] outlinks = parseData.getOutlinks();
    Inlinks inlinks = new Inlinks();
    for (int i = 0; i < outlinks.length; i++) {
      Outlink outlink = outlinks[i];
      String toUrl = outlink.getToUrl();

      toUrl = urlNormalizers.normalize(toUrl, URLNormalizers.SCOPE_LINKDB);
      toUrl = urlFilters.filter(toUrl);

      inlinks.clear();
      String anchor = outlink.getAnchor();
      if (anchor.length() > maxAnchorLength) {
        anchor = anchor.substring(0, maxAnchorLength);
      }
      inlinks.add(new Inlink(fromUrl, anchor));
      output.collect(new Text(toUrl), inlinks);
    }
  }

map函数取出parse_data文件夹下记录的从某个url即fromUrl提取出的所有链接outlinks,进行标准化和过滤,最后输出的key为outlinks中每个链接,value为fromUrl。

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

  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
08-10
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值