`
xtfncel
  • 浏览: 74382 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Nutch中使用自定义中文分词器

阅读更多

Nutch中使用自定义中文分词器

Nutch对中文查询时默认采用的分词器为NutchAnalyzer,对中文默认采用单字切分.这种效果不是很理想,我们可以自定义切词器,以实现对中文支持.

通常可以采用的两种方式添加对中文的支持:

    1.采用插件的方式,不修改系统代码的基础上,编写中文分词插件实现对中文分词的支持。

2.直接修改nutch的系统代码,对默认的分词器代码进行修改使其使用自定义中文分词程序.

1.插件方式

1.1实现思路

通过nutch插件机制实现。根据nutch提供的NutchAnalyzer扩展点,实现自定义的扩展。在插件中实现自定义的中文分词逻辑。

1.2插件流程

Nutch根据不同的语言使用不同的分词器来分词。Nutch如何判定现在分析的网页是那个语言的网页?Nutch使用一个外部Pluginlanguage-identifier来确定当前分析的网页是那种语言的网页。然后在当前的Document中放入一个名为langField。在进行索引创建和搜索的时候,都会根据lang选择对应语言的Analyzer,如果没有lang的信息,那么Nutch会使用默认的AnalyzerDocument建立索引。通过这样的过程就实现了Nutch使用不同的分词器分析不同的网页。

NutchAnalyzer analyzer = factory.get(doc.get("lang"));

Factory AnalyzerFactory会根据不同的语言获取切词器而这里的lang属性则通过 Languageidentifier来实现。

1.3实现步骤

1.3.1建立插件类

public class MyAnalyzer extends NutchAnalyzer{

    private final static Analyzer ANALYZER = new SimpleAnalyzer();

    public static final Log LOG = LogFactory.getLog(MyAnalyzer.class);

    @Override

    public TokenStream tokenStream(String fieldName, Reader reader) {

       System.out.println("调用了自已写的中文分词插件....");

       return ANALYZER.tokenStream(fieldName, reader);

    }

 

}

这里为了演示方便只是简单的调用了lucene中的SimpleAnalyzer分词器的分词方法。

1.3.2建立插件配置文件:plugin.xml

<plugin id="MyAnalyzer-zh"   name="Analyzer_self"

        version="1.0.0"  provider-name="nutch.org"> 

    <runtime>

        <library name="MyAnalyzer-zh.Jar"><export name="*"/></library>

    </runtime>

    <requires>

        <import plugin="nutch-extensionpoints"/>

    </requires>

    <extension id="com.gpower.nutch.plugin.MyAnalyzer"

               name="Self Nutch Plugin Analyzer"

               point="org.apache.nutch.analysis.NutchAnalyzer">

       <implementation id="myAnalyzer_"

              class="com.gpower.nutch.plugin.MyAnalyzer">

           <parameter name="lang" value="zh"/>

       </implementation>

    </extension>

</plugin>

1.3.3修改nutch配置信息 :nutch-site.xml(加入新建立的插件)

<property>

<name>plugin.includes</name>  <value>protocol-http|urlfilter-regex|parse-(text|html|js|tika)|index-(basic|anchor)|query-(basic|site|url)|response-(json|xml)|summary-basic|scoring-opic|urlnormalizer-(pass|regex|basic)|MyAnalyzer-zh</value>

<description>……</description>

</property>

       1.3.4将插件打包成jar文件,与plugin.xml文件一并放入plugins/下,如图:

      

       1.3.5调用流程分析

    我们先来看看nutch中是如何调用获得分词插件的。

    AnalyzerFactory类中有以下几个相关方法:

    public NutchAnalyzer get(String lang) {

 

    NutchAnalyzer analyzer = DEFAULT_ANALYZER;//获得nutch默认的分词器

    Extension extension = getExtension(lang);//根据参数获得相应扩展

    if (extension != null) {

        try {

//获得扩展的实例,也就是我们实现的那个插件了。

            analyzer = (NutchAnalyzer) extension.getExtensionInstance();

        } catch (PluginRuntimeException pre) {

            analyzer = DEFAULT_ANALYZER;

        }

    }

    return analyzer;

  }

 

  private Extension getExtension(String lang) {

    ObjectCache objectCache = ObjectCache.get(conf);

    if (lang == null) { return null; }

    Extension extension = (Extension) objectCache.getObject(lang);//先去缓存里找相应扩展,如果有则直接从缓存返回。

    if (extension == null) {

      extension = findExtension(lang);

      if (extension != null) {

        objectCache.setObject(lang, extension);

      }

    }

    return extension;

  }

 

  private Extension findExtension(String lang) {

 

    if (lang != null) {

      Extension[] extensions = this.extensionPoint.getExtensions();//获得该扩展点(NutchAnalyzer)下所有扩展

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

        if (lang.equals(extensions[i].getAttribute("lang"))) {// getAttribute的值就是plugin.xml中扩展点配置的lang属性

          return extensions[i];

        }

      }

    }

    return null;

  }

以上就完成了一个自定义中文分词的插件,运行nutch后就应该使用的是笔者自定义的中文分词插件了,但经过笔者测试,这时的中文分词插件并没有起作用。什么原因呢?

原来调用get(lang)方法时,lang的值为空,所以就自动使用还是nutch默认的分词了,因此笔者又作了如下的改到,以建立索引时的调用为例:

LuceneWriter:

  public void write(NutchDocument doc) throws IOException {

    final Document luceneDoc = createLuceneDoc(doc);

    //change by me

    String lang = null;

    if(luceneDoc.get("lang")==null){

    lang = "zh";

    }

    final NutchAnalyzer analyzer = analyzerFactory.get(lang);

    // end

//  final NutchAnalyzer analyzer = analyzerFactory.get(luceneDoc.get("lang"));

    if (Indexer.LOG.isDebugEnabled()) {

      Indexer.LOG.debug("Indexing [" + luceneDoc.get("url")

          + "] with analyzer " + analyzer + " (" + luceneDoc.get("lang")

          + ")");

    }

    writer.addDocument(luceneDoc, analyzer);

}

    改成这样后程序可以按预测结果正常运行,如下图内容;具体原因大约和language-identifier插件对中文的支持有关吧。还有待后续的研究吧。不管怎样,总算是可以实现nutch中加入自定义中文分词插件了。

        1.3.6测试结果

 

2.修改nutch默认分词器

    Nutch 本身提供了一个默认的分词器:NutchDocumentAnalyzer。我们可通过修改该类的具体实现来改用我们自定义的分词器,部分代码如下:

private static Analyzer  MY_ANALYZER;
public NutchDocumentAnalyzer(Configuration conf) {

  //
  MY_ANALYZER = new MyAnalyzer();
}

  public TokenStream tokenStream(String fieldName, Reader reader) {
    Analyzer analyzer;
    
/*
    if ("anchor".equals(fieldName))
      analyzer = ANCHOR_ANALYZER;
    else
      analyzer = CONTENT_ANALYZER;
    */

    analyzer =  MY_ANALYZER;    
    
return analyzer.tokenStream(fieldName, reader);
  }

 

说白了就是将默认分词器换成我们自定义的分词器调用就可以了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics