`
cz05141331
  • 浏览: 4395 次
  • 性别: 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-2.1源代码

    Nutch 是一个开源Java 实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。 本资源官网上下的源代码。 nutch-2.1 适用于windows系统

    nutch 1.5的源代码

    nutch源代码,共享给大家。nutch是一个开源的搜索引擎

    lucene nutch 搜索引擎 开发 实例 源代码 源码

    lucene nutch 搜索引擎 开发 实例 源代码 源码 包含lucene使用的所有源代码,从建立索引,搜索,删除,排序,都有,非常齐全 还有PDF 解析,WORD解析 ,EXCEL,ppt,xml解析等,,都有源码实现 还有nutch源码,spider...

    Lucene+nutch搜索引擎开发 源代码

    《Lucene+nutch搜索引擎开发》书附带的源代码

    nutch 0.9分页代码(粘贴可用)

    nutch 0.9分页代码(粘贴可用)

    nutch开发工程代码2

    nutch开发工程代码2nutch开发工程代码2nutch开发工程代码2

    apache-nutch-2.3.1 源码和构建好的库文件等 (part 4)

    相对于那些商用的搜索引擎, Nutch作为开放源代码 搜索引擎将会更加透明, 从而更值得大家信赖. 现在所有主要的搜索引擎都采用私有的排序算法, 而不会解释为什么一个网页会排在一个特定的位置. 除此之外, 有的搜索...

    nutch开发工程代码1

    nutch开发工程代码1,一些源代码,拿去看看吧,说不定能帮上忙

    Lucene+nutch搜索引擎开发(源代码)

    Lucene+nutch搜索引擎开发(源代码),内含本书的PDF电子下载地址。

    nutch crawl代码解析

    nutch虽然是开源的,但初学nutch的同志门肯定对源码比较头疼,很难看懂,本资料是对crawl源码的解析,希望对大家有用。

    Nutch 解析器parse部分代码笔记

    Nutch 解析器parse部分代码笔记

    网络蜘蛛程序源代码nutch0·8

    网络蜘蛛程序源代码nutch0·8,压缩文件

    Apache Nutch源代码

    Nutch的创始人是Doug Cutting,他同时也... Nutch诞生于2002年8月,是Apache旗下的一个用Java实现的开源搜索引擎项目,自Nutch1.2版本之后,Nutch已经从搜索引擎演化为网络爬虫,接着Nutch进一步演化为两大分支版本:1.

    nutch爬虫资料

    包括nutch的参考书,和NUTCH源代码分析

    nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据

    nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据nutch 爬虫数据

    lucene+nutch代码

    lucene和nutch的一些源代码 适合想学习搜索引擎的同学学习

    Nutch中文教程nutcher.zip

    nutcher致力于为nutch提供一个较新的中文教程和文档,供开发者学习。 github地址: https://github.com/CrawlScript/nutcher 目录: Nutch教程——导入Nutch工程,执行完整爬取 ...

    apache-nutch-2.3.1 源码和构建好的库文件等 (part 2)

    相对于那些商用的搜索引擎, Nutch作为开放源代码 搜索引擎将会更加透明, 从而更值得大家信赖. 现在所有主要的搜索引擎都采用私有的排序算法, 而不会解释为什么一个网页会排在一个特定的位置. 除此之外, 有的搜索...

    nutch入门教程

    (1) 透明度:nutch 是开放源代码的,因此任何人都可以查看他的排序算法 是如何工作的。商业的搜索引擎排序算法都是保密的,我们无法知道为 什么搜索出来的排序结果是如何算出来的。更进一步,一些搜索引擎允 许竞价...

Global site tag (gtag.js) - Google Analytics