`
cz05141331
  • 浏览: 4491 次
  • 性别: Icon_minigender_1
  • 来自: 南京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Nutch index源代码解析(一)

阅读更多

Nutch集成slor的索引方法介绍

/**

   * 建立索引

   * @param solrUrl solr的web地址

   * @param crawlDb 爬取DB的存放路径:\crawl\crawldb

   * @param linkDb 爬取link的存放路径:\crawl\linkdb

   * @param segments 元数据存放路径:\crawl\segments

   * @param noCommit  是否提交slor服务器跟下slor索引

   * @param deleteGone 是否删除过时的文档

   * @param solrParams solr的参数

   * @param filter 是否启用URL过滤

   * @param normalize 是否格式化 URL

   * @throws IOException

   */

  public void indexSolr(String solrUrl, Path crawlDb, Path linkDb,

      List<Path> segments, boolean noCommit, boolean deleteGone, String solrParams,

      boolean filter, boolean normalize) throws IOException {

        ...

       IndexerMapReduce.initMRJob(crawlDb, linkDb, segments, job);

        ...

   }

Nutch的索引,是通过一个MR完成的。

map的输入是Nutch爬去目录下的sequenceFile ,key是Nutch爬取下来的URL,value使用的java泛型,将所有nutch自定义的数据类型抽象成一个NutchWritable对象。

Nutchwritable的包含的的数据类型如下源代码:

CLASSES = new Class[] {

      org.apache.hadoop.io.NullWritable.class,

      org.apache.hadoop.io.BooleanWritable.class,

      org.apache.hadoop.io.LongWritable.class,

      org.apache.hadoop.io.BytesWritable.class,

      org.apache.hadoop.io.FloatWritable.class,

      org.apache.hadoop.io.IntWritable.class,

      org.apache.hadoop.io.MapWritable.class,

      org.apache.hadoop.io.Text.class,

      org.apache.hadoop.io.MD5Hash.class,

      org.apache.nutch.crawl.CrawlDatum.class,

      org.apache.nutch.crawl.Inlink.class,

      org.apache.nutch.crawl.Inlinks.class,

      org.apache.nutch.fetcher.FetcherOutput.class,

      org.apache.nutch.metadata.Metadata.class,

      org.apache.nutch.parse.Outlink.class,

      org.apache.nutch.parse.ParseText.class,

      org.apache.nutch.parse.ParseData.class,

      org.apache.nutch.parse.ParseImpl.class,

      org.apache.nutch.parse.ParseStatus.class,

      org.apache.nutch.protocol.Content.class,

      org.apache.nutch.protocol.ProtocolStatus.class,

      org.apache.nutch.scoring.webgraph.LinkDatum.class,

    };

这些数据类型分别抽象了Nutch在爬取时各个阶段的数据类型。

map阶段不对value进行处理,只对URL进行处理,处理代码如下:

   String urlString = filterUrl(normalizeUrl(key.toString()));

调用是对URL根据定义好的过滤规则对URL进行过滤和格式化,当然是否进行这步操作可以通过调用命令时参数设置。

reduce是对所有爬取的数据进行处理,代码注释如下:

 /**

   * 输出格式:url作为key,索引的action作为value

   */

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

                     OutputCollector<Text, NutchIndexAction> output, Reporter reporter)

    throws IOException {

    Inlinks inlinks = null;

    CrawlDatum dbDatum = null;

    CrawlDatum fetchDatum = null;

    ParseData parseData = null;

    ParseText parseText = null;

 

    while (values.hasNext()) {

      final Writable value = values.next().get(); // unwrap

      //如果是URL注入的数据类型

      if (value instanceof Inlinks) {

        inlinks = (Inlinks)value;

        //如果是爬取的数据类型

      } else if (value instanceof CrawlDatum) {

        final CrawlDatum datum = (CrawlDatum)value;

        //如果当前数据处于db注入状态

        if (CrawlDatum.hasDbStatus(datum)) {

          dbDatum = datum;

        }

        //如果当前数据处于爬取完成状态。

        else if (CrawlDatum.hasFetchStatus(datum)) {

 

          // don't index unmodified (empty) pages

          //判断爬去的是否进行了修改

          if (datum.getStatus() != CrawlDatum.STATUS_FETCH_NOTMODIFIED) {

            fetchDatum = datum;

 

            /**

             * Check if we need to delete 404 NOT FOUND and 301 PERMANENT REDIRECT.

             */

            //参数中如果设置删除为true则删除错误及过时的页面

            if (delete) {

            //如果爬取的页面过期,采取删除操作。

              if (fetchDatum.getStatus() == CrawlDatum.STATUS_FETCH_GONE) {

                reporter.incrCounter("IndexerStatus", "Documents deleted", 1);

 

                NutchIndexAction action = new NutchIndexAction(null, NutchIndexAction.DELETE);

                output.collect(key, action);

                return;

              }

              //如果爬去的页面已经重定向到另外一个页面,才去删除操作。

              if (fetchDatum.getStatus() == CrawlDatum.STATUS_FETCH_REDIR_PERM) {

                reporter.incrCounter("IndexerStatus", "Perm redirects deleted", 1);

 

                NutchIndexAction action = new NutchIndexAction(null, NutchIndexAction.DELETE);

                output.collect(key, action);

                return;

              }

            }

          }

         //URL是通过其他URL被发现的 ||页面的签名||页面的元数据是通过解析器产生的

        } else if (CrawlDatum.STATUS_LINKED == datum.getStatus() ||

                   CrawlDatum.STATUS_SIGNATURE == datum.getStatus() ||

                   CrawlDatum.STATUS_PARSE_META == datum.getStatus()) {

          continue;

        } else {

          throw new RuntimeException("Unexpected status: "+datum.getStatus());

        }

       //如果是解析的数据类型

      } else if (value instanceof ParseData) {

        parseData = (ParseData)value;

 

        // Handle robots meta? https://issues.apache.org/jira/browse/NUTCH-1434

        if (deleteRobotsNoIndex) {

          // Get the robots meta data

          String robotsMeta = parseData.getMeta("robots");

 

          // Has it a noindex for this url?

          if (robotsMeta != null && robotsMeta.toLowerCase().indexOf("noindex") != -1) {

            // Delete it!

            NutchIndexAction action = new NutchIndexAction(null, NutchIndexAction.DELETE);

            output.collect(key, action);

            return;

          }

        }

        //解析完的Text文件

      } else if (value instanceof ParseText) {

        parseText = (ParseText)value;

      } else if (LOG.isWarnEnabled()) {

        LOG.warn("Unrecognized type: "+value.getClass());

      }

    }

    //如果只有链接,没有爬取历史的记录或者爬取数据直接返回

    if (fetchDatum == null || dbDatum == null

        || parseText == null || parseData == null) {

      return;                                     // only have inlinks

    }

 

    // Whether to skip DB_NOTMODIFIED pages

    //如果页面被爬取过,但是没有进行修过,在传进来的命令中设置了跳过则跳过。

    if (skip && dbDatum.getStatus() == CrawlDatum.STATUS_DB_NOTMODIFIED) {

      reporter.incrCounter("IndexerStatus", "Skipped", 1);

      return;

    }

    //页面爬去成功,但是解析失败的,直接返回

    if (!parseData.getStatus().isSuccess() ||

        fetchDatum.getStatus() != CrawlDatum.STATUS_FETCH_SUCCESS) {

      return;

    }

 

    NutchDocument doc = new NutchDocument();

    //解析完的数据中获取页面的元数据

    final Metadata metadata = parseData.getContentMeta();

 

    // add segment, used to map from merged index back to segment files

    doc.add("segment", metadata.get(Nutch.SEGMENT_NAME_KEY));

    //页面摘要

    // add digest, used by dedup

    doc.add("digest", metadata.get(Nutch.SIGNATURE_KEY));

    

    final Parse parse = new ParseImpl(parseText, parseData);

    try {

      // extract information from dbDatum and pass it to

      // fetchDatum so that indexing filters can use it

      final Text url = (Text) dbDatum.getMetaData().get(Nutch.WRITABLE_REPR_URL_KEY);

      if (url != null) {

        fetchDatum.getMetaData().put(Nutch.WRITABLE_REPR_URL_KEY, url);

      }

      // run indexing filters

      //执行所有过滤器

      doc = this.filters.filter(doc, parse, key, fetchDatum, inlinks);

    } catch (final IndexingException e) {

      if (LOG.isWarnEnabled()) { LOG.warn("Error indexing "+key+": "+e); }

      reporter.incrCounter("IndexerStatus", "Errors", 1);

      return;

    }

 

    // skip documents discarded by indexing filters

    if (doc == null) {

      reporter.incrCounter("IndexerStatus", "Skipped by filters", 1);

      return;

    }

 

    float boost = 1.0f;

    // run scoring filters

    //执行评分过滤器

    try {

      boost = this.scfilters.indexerScore(key, doc, dbDatum,

              fetchDatum, parse, inlinks, boost);

    } catch (final ScoringFilterException e) {

      if (LOG.isWarnEnabled()) {

        LOG.warn("Error calculating score " + key + ": " + e);

      }

      return;

    }

    //将评分作为文档的权重

    // apply boost to all indexed fields.

    doc.setWeight(boost);

    // store boost for use by explain and dedup

    doc.add("boost", Float.toString(boost));

 

    reporter.incrCounter("IndexerStatus", "Documents added", 1);

 

    NutchIndexAction action = new NutchIndexAction(doc, NutchIndexAction.ADD);

    output.collect(key, action);

  }

目前研究到此,后面的待续。。

1
0
分享到:
评论

相关推荐

    nutch使用&Nutch;入门教程

    在使用Nutch之前,你需要配置Nutch的运行环境,包括安装Java、设置Hadoop(如果需要分布式爬取)、下载和编译Nutch源代码。还需要配置Nutch的`conf/nutch-site.xml`文件,指定抓取策略、存储路径、爬虫范围等参数。 ...

    搭建nutch web开发环境

    1. 使用Git克隆Nutch 1.2的源代码库: ``` git clone https://github.com/apache/nutch.git -b branch-1.2 ``` **构建Nutch** 1. 进入Nutch源代码目录: ``` cd nutch ``` 2. 使用Maven构建Nutch: ``` mvn...

    关于Nutch的安装

    Nutch的源代码可以通过两种方式获取: - **下载发行版**:从官方网站`http://lucene.apache.org/nutch/release/`下载最新版本的Nutch,然后解压缩到你选择的目录。 - **使用Subversion**:如果你想要获取最新的源...

    搭建nutch开发环境步骤

    这将创建一个名为`nutch`的目录,包含了项目的全部源代码。 **步骤四:配置Nutch** 进入`nutch`目录,打开`conf/nutch-site.xml`文件,根据你的需求进行配置。例如,你可以修改抓取间隔、抓取策略等。 **步骤五:...

    Nutch_插件深入研究

    Nutch插件允许开发者根据特定需求定制和扩展Nutch的功能,如自定义爬虫策略、数据解析方式、索引处理逻辑等。 #### 二、Nutch插件开发详解 Nutch插件的开发涉及到以下几个关键步骤: 1. **创建插件目录结构**:...

    分享一个Nutch入门学习的资料

    安装Nutch涉及到Java环境、Hadoop环境的配置,以及Nutch源代码的编译。初学者需要确保Java版本符合要求,安装并配置好Hadoop,然后从Apache官方网站下载Nutch源代码,通过Maven进行编译和构建。 5. **Nutch配置...

    Nutch 0.8笔记NUTCHNUTCH

    1. **文档阅读**:深入了解 Nutch 需要阅读官方提供的文档,如 "Introduction to Nutch, Part 1 Crawling" 和 "Introduction to Nutch, Part 2 Searching",以及源代码。Nutch 的源码结构清晰,便于理解和学习。 2....

    nutch-0.9 环境搭建所需最小cygwin

    3. **构建Nutch**:在Cygwin终端中,导航到Nutch的源代码目录,然后运行`ant`命令来编译Nutch。这个过程会生成所需的类文件和配置文件。 4. **配置Nutch**:根据你的需求修改Nutch的配置文件,主要是在`conf`目录下...

    nutch网页爬取总结

    - **配置 Nutch 创建索引**:下载 Nutch 的源代码并解压,然后通过 Maven 进行编译。配置 Nutch 的 `conf/nutch-site.xml` 文件以设置存储路径、抓取策略等参数。 - **安装 Tomcat**:Tomcat 用于运行 Nutch 的 UI...

    nutch2.2.1

    - `src`: 源代码目录,包含了所有Nutch的Java源码。 - `conf`: 配置文件,如`nutch-default.xml`和`nutch-site.xml`,需要根据实际需求进行调整。 - `bin`: 包含运行Nutch的各种脚本。 - `build.xml`: Ant构建文件,...

    nutch入门教程

    用户可以通过修改Nutch的源代码来定制和优化搜索引擎,以适应特定的需求或环境。 **8.2 插件机制---plugin** Nutch的插件机制允许用户扩展Nutch的功能,例如增加新的抓取协议、改进搜索算法等。插件机制增加了...

    nutch支持书名号搜索原理解释及代码实现

    例如,可能需要修改分析器(Analyzer)、查询解析器(QueryParser)和索引字段(IndexField)的代码,以确保书名号的正确处理。 在提供的文件列表中,"书名号搜索*.png" 可能是相关流程的截图,展示了一些关键步骤...

    \Lucene Nutch和安装说明文旦

    3. **构建项目**: 使用Maven或Gradle等构建工具编译源代码,生成可执行的JAR文件。 4. **配置文件**: 修改Nutch的配置文件,如`conf/nutch-site.xml`,设置爬虫的基本参数,如抓取间隔、抓取策略等。 5. **初始化...

    apache-nutch-1.3-src.tar.gz_nutch_nutch-1.3.tar.gz

    这个源码包 "apache-nutch-1.3-src.tar.gz" 和 "nutch-1.3.tar.gz" 包含了 Nutch 1.3 的源代码和编译后的二进制文件,对于开发者和研究者来说是非常有价值的资源。 **Nutch 概述** Nutch 是基于 Java 开发的,遵循 ...

    Nutch 使用总结

    5. `src`:Nutch的源代码目录。 6. `webapps`:包含了基于Tomcat的应用程序包,如`nutch-0.9.war`。 Nutch 的基本使用步骤: 1. 安装准备工作:确保系统安装了Cygwin、JDK(1.4.2以上版本)、Nutch(推荐0.9版本)...

    Nutch插件开发和服务器发布流程

    - 将插件的源代码保存在`/src/java/org/apache/nutch/parse/self/`目录下。在这个示例中,我们将实现一个名为`indexingFilter`的插件。 - 需要注意的是,插件的类应该遵循Nutch的命名规范,确保与其他模块兼容。 **...

    nutch入门学习

    Nutch 的安装通常包括下载源代码或发行版、解压、配置环境变量以及设置必要的配置文件等步骤。Nutch 的配置文件主要有 `conf/nutch-site.xml` 和 `conf/solrconfig.xml` 等,用于指定索引存储位置、日志级别等参数。...

    lucene+nutch搜索引擎(12章源码)

    3. 开放源代码:社区活跃,有大量的插件和教程供开发者参考。 四、实际应用场景 1. 内容管理系统:在企业内部构建信息检索平台,帮助员工快速找到所需资料。 2. 新闻门户:提供新闻内容的即时搜索,提升用户体验。...

Global site tag (gtag.js) - Google Analytics