关于几种中文分词的比对
目前lucene自身提供的StandardAnalyzer已经具备中文分词的功能,但是不一定能够满足大多数应用的需要。?
另外网友谈的比较多的中文分词器还有:?
CJKAnalyzer?
ChineseAnalyzer?
IK_CAnalyzer(MIK_CAnalyzer)?
还有一些热心网友自己写的比较不错的分词器在此就不说了,有兴趣的可以自己研究研究。?
以上三个中文分词器并不是lucene2.2.jar里提供的。?
CJKAnalyzer和ChineseAnalyzer分别是lucene-2.2.0目录下contrib目录下analyzers的lucene-analyzers-2.2.0.jar提供的。分别位于cn和cjk目录。?
IK_CAnalyzer(MIK_CAnalyzer)是基于分词词典,目前最新的1.4版本是基于lucene2.0开发的。以上分词器各有优劣,比较如下:?
import ? java.io.Reader;?
import ? java.io.StringReader;?
import ? org.apache.lucene.analysis.Analyzer;?
import ? org.apache.lucene.analysis.StopFilter;?
import ? org.apache.lucene.analysis.Token;?
import ? org.apache.lucene.analysis.TokenFilter;?
import ? org.apache.lucene.analysis.TokenStream;?
import ? org.apache.lucene.analysis.cjk.CJKAnalyzer;?
import ? org.apache.lucene.analysis.cn.ChineseAnalyzer;?
import ? org.apache.lucene.analysis.standard.StandardAnalyzer;?
import ? org.mira.lucene.analysis.IK_CAnalyzer;?
import ? org.mira.lucene.analysis.MIK_CAnalyzer;?
?
public ? class ? All_Test ? {?
?? ? ? ? ?private ? static ? String ? string ? = ? "中华人民共和国在1949年建立,从此开始了新中国的伟大篇章。 ";?
?? ? ? ? ?public ? static ? void ? Standard_Analyzer(String ? str) ? throws ? Exception{?
?? ? ? ? ? ? ? ? ? ? ? ?Analyzer ? analyzer ? = ? new ? StandardAnalyzer(); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?Reader ? render ? = ? new ? StringReader(str); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?StopFilter ? stopFilter ? = ? (StopFilter) ? analyzer.tokenStream( " ", ? render ?);?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "=====StandardAnalyzer==== ");?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "分析方法:默认没有词只有字(一元分词) ");?
?? ? ? ? ? ? ? ? ? ? ? ?Token ? token; ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ?while ? ((token ? = ? stopFilter.next()) ? != ? null) ? { ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?System.out.println(token.termText()); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ??
?? ? ? ? ? ?}?
?? ? ? ? ?public ? static ? void ? CJK_Analyzer(String ? str) ? throws ? Exception{?
?? ? ? ? ? ? ? ? ? ? ? ?Analyzer ? analyzer ? = ? new ? CJKAnalyzer(); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?Reader ? render ? = ? new ? StringReader(str); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?StopFilter ? stopFilter ? = ? (StopFilter) ? analyzer.tokenStream( " ", ? render);?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "=====CJKAnalyzer==== ");?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "分析方法:交叉双字分割(二元分词) ");?
?? ? ? ? ? ? ? ? ? ? ? ?Token ? token; ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ?while ? ((token ? = ? stopFilter.next()) ? != ? null) ? { ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?System.out.println(token.termText()); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?
?? ? ? ? ? ?}?
?? ? ? ? ?public ? static ? void ? Chiniese_Analyzer(String ? str) ? throws ? Exception{?
?? ? ? ? ? ? ? ? ? ? ? ?Analyzer ? analyzer ? = ? new ? ChineseAnalyzer(); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?Reader ? render ? = ? new ? StringReader(str); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?TokenFilter ? tokenFilter ? = ? (TokenFilter) ? analyzer.tokenStream( " ", ? render);?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "=====chinese ? analyzer==== ");?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "分析方法:基本等同StandardAnalyzer(一元分词) ");?
?? ? ? ? ? ? ? ? ? ? ? ?Token ? token; ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ?while ? ((token ? = ? tokenFilter.next()) ? != ? null) ? { ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?System.out.println(token.termText()); ? ? ? ? ? ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ??
?? ? ? ? ? ?}?
?? ? ? ? ?public ? static ? void ? ik_CAnalyzer(String ? str) ? throws ? Exception{?
// ? ? ? ? ? ? ? ? ? ? Analyzer ? analyzer ? = ? new ? MIK_CAnalyzer();?
?? ? ? ? ? ? ? ? ? ? ? ?Analyzer ? analyzer ? = ? new ? IK_CAnalyzer();?
?? ? ? ? ? ? ? ? ? ? ? ?Reader ? reader ? = ? new ? StringReader(str); ??
?? ? ? ? ? ? ? ? ? ? ? ?TokenStream ? tokenStream ? = ? (TokenStream)analyzer.tokenStream( " ", ? reader);?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "=====IK_CAnalyzer==== ");?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "分析方法:字典分词,正反双向搜索 ");?
?? ? ? ? ? ? ? ? ? ? ? ?Token ? token; ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ?while ? ((token ? = ? tokenStream.next()) ? != ? null) ? { ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?System.out.println(tokenStream.termText()); ? ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ??
?? ? ? ? ? ?}?
?? ? ? ? ?public ? static ? void ? main(String[] ? args) ? throws ? Exception{?
?? ? ? ? ? ? ? ? ? ? ? ?String ? str ? = ? string;?
?? ? ? ? ? ? ? ? ? ? ? ?System.out.println( "我们测试的字符串是: "+str);?
?
?? ? ? ? ? ? ? ? ? ? ? ?Standard_Analyzer(str);?
?? ? ? ? ? ? ? ? ? ? ? ?CJK_Analyzer(str);?
?? ? ? ? ? ? ? ? ? ? ? ?Chiniese_Analyzer(str);?
?? ? ? ? ? ? ? ? ? ? ? ?ik_CAnalyzer(str);?
?? ? ? ? ? ?}?
?
}?
分词结果如下:?
我们测试的字符串是:中华人民共和国在1949年建立,从此开始了新中国的伟大篇章。?
=====StandardAnalyzer====?
分析方法:默认没有词只有字(一元分词)?
中?
华?
人?
民?
共?
和?
国?
在?
1949?
年?
建?
立?
从?
此?
开?
始?
了?
新?
中?
国?
的?
伟?
大?
篇?
章?
=====CJKAnalyzer====?
分析方法:交叉双字分割(二元分词)?
中华?
华人?
人民?
民共?
共和?
和国?
国在?
1949?
年建?
建立?
从此?
此开?
开始?
始了?
了新?
新中?
中国?
国的?
的伟?
伟大?
大篇?
篇章?
=====chinese ? analyzer====?
分析方法:基本等同StandardAnalyzer(一元分词)?
中?
华?
人?
民?
共?
和?
国?
在?
年?
建?
立?
从?
此?
开?
始?
了?
新?
中?
国?
的?
伟?
大?
篇?
章?
=====IK_CAnalyzer====?
分析方法:字典分词,正反双向搜索?
中华人民共和国?
中华人民?
中华?
华人?
人民共和国?
人民?
人?
共和国?
共和?
1949年?
建立?
从此?
开始?
新中国?
中国?
伟大?
大篇?
篇章?
如果 ? ik_CAnalyzer(String ? str) ? 里采用?
Analyzer ? analyzer ? = ? new ? MIK_CAnalyzer();?
那么该方法的分词结果是:?
?
中华人民共和国?
1949年?
建立?
从此?
开始?
新中国?
伟大?
大篇?
篇章?
?
可以看到各种分词结果各不相同,根据应用的需要可以选择合适的分词器。?
关于IKAnalyzer的介绍可以参考:?
http://blog.csdn.net/dbigbear/archive/2007/01/24/1492380.aspx
http://topic.csdn.net/u/20070714/13/84db902a-9128-4b1b-8dd8-a631f15db931.html
?
?
//测试"庖丁解牛"中文分词器的分词效果 ? ??
?? ?public class PaodingAnalyzer {?
?? ? ? ?public static void main(String[] args) throws Exception {?
?? ? ? ? ? ?Analyzer analyzer = new PaodingAnalyzer();?
?? ? ? ? ? ?String ?indexStr = "我的QQ号码是38334641";?
?? ? ? ? ? ?StringReader reader = new StringReader(indexStr);?
?? ? ? ? ? ?TokenStream ts = analyzer.tokenStream(indexStr, reader);?
?? ? ? ? ? ?Token t = ts.next();?
?? ? ? ? ? ?while (t != null) {?
?? ? ? ? ? ? ? ?System.out.print(t.termText()+" ?");?
?? ? ? ? ? ? ? ?t = ts.next();?
?? ? ? ? ? ?}?
?? ? ? ?}?
?? ?}?
分词结果:我的 ?qq ?号码 ?38334641 ??
如果把indexStr换成是"中华人民共和国万岁" ,那么分词结果为:?
中华 ?华人 ?人民 ?共和 ?共和国 ?万岁 ??