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

原文:http://xtfncel.iteye.com/blog/756763

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

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

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

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

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

1.插件方式

1.1实现思路

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

1.2插件流程

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

 

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注