这应该是我第二次写IK中文分词的相关东西了。话说IK真心好用,最开始就用过IK的搜索后来又用它和solr结合使用。
关于IK可以参考下官方文档的介绍,使用配置也有相关的pdf文档。http://www.oschina.net/p/ikanalyzer
今天仅仅使用到了IK的分词功能。所以代码很简单,我就直接贴上来了。
这个代码主要是对传入的参数进行分词,并统计好每个次的频率。代码如下:
public static Map getTextDef(String text) throws IOException {
Map<String, Integer> wordsFren=new HashMap<String, Integer>();
IKSegmenter ikSegmenter = new IKSegmenter(new StringReader(text), true);
Lexeme lexeme;
while ((lexeme = ikSegmenter.next()) != null) {
if(lexeme.getLexemeText().length()>1){
if(wordsFren.containsKey(lexeme.getLexemeText())){
wordsFren.put(lexeme.getLexemeText(),wordsFren.get(lexeme.getLexemeText())+1);
}else {
wordsFren.put(lexeme.getLexemeText(),1);
}
}
}
return wordsFren;
}
代码很简单,主要介绍下IK中的类,IKSegmenter是分词的主要类,其参数分别是分词的句子或者文章,后面的参数是是否开启智能模式,不开启就按最小词义分。
分词的结果是Lexeme这个类,用其中的getLexemeText()方法就能取出相关的分词结果。
接下来是计算词频,将分词结果和出现次数放到一个map结构中,map的value对应了词的出现次数。这里注意一下,我只记录两个字及两个字以上的分词结果。
public static void sortSegmentResult(Map<String,Integer> wordsFrenMaps,int topWordsCount){
System.out.println("排序前:================");
Iterator<Map.Entry<String,Integer>> wordsFrenMapsIterator=wordsFrenMaps.entrySet().iterator();
while (wordsFrenMapsIterator.hasNext()){
Map.Entry<String,Integer> wordsFrenEntry=wordsFrenMapsIterator.next();
System.out.println(wordsFrenEntry.getKey()+" 的次数为"+wordsFrenEntry.getValue());
}
List<Map.Entry<String, Integer>> wordFrenList = new ArrayList<Map.Entry<String, Integer>>(wordsFrenMaps.entrySet());
Collections.sort(wordFrenList, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> obj1, Map.Entry<String, Integer> obj2) {
return obj2.getValue() - obj1.getValue();
}
});
System.out.println("排序后:================");
for(int i=0;i<topWordsCount&&i<wordFrenList.size();i++){
Map.Entry<String,Integer> wordFrenEntry=wordFrenList.get(i);
if(wordFrenEntry.getValue()>1){
System.out.println(wordFrenEntry.getKey()+" 的次数为"+wordFrenEntry.getValue());
}
}
}
这个方法主要对分词结果及词频按照出现次数排序,没有自己去写实现,主要借用了collections的sort方法。
测试方法如下:
public static void main(String args[]) throws IOException {
String text = "IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目 Lucene为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为 面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。\n" +
"\n" +
"IKAnalyzer3.0特性:\n" +
"\n" +
"采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。\n" +
"\n" +
"采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。\n" +
"\n" +
"优化的词典存储,更小的内存占用。支持用户词典扩展定义\n" +
"\n" +
"针对Lucene全文检索优化的查询分析器IKQueryParser(作者吐血推荐);采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。";
int topWordsCount=3;
Map<String,Integer> wordsFrenMaps=getTextDef(text);
sortSegmentResult(wordsFrenMaps,topWordsCount);
}
输出结果为:
加载扩展词典:ikdict/ext.dic
加载扩展停止词典:ikdict/english_stopword.dic
加载扩展停止词典:ikdict/chinese_stopword.dic
排序前:================
ikanalyzer3.0 的次数为2
开源 的次数为2
开发 的次数为1
姓名 的次数为1
lucene 的次数为5
内存 的次数为1
词汇 的次数为1
支持 的次数为2
英文字母 的次数为1
查询 的次数为2
面向 的次数为1
采用 的次数为1
12月 的次数为1
推荐 的次数为1
ikanalyzer 的次数为2
地名 的次数为1
默认 的次数为1
提供 的次数为1
特性 的次数为1
地址 的次数为1
中文 的次数为4
文法 的次数为1
组件 的次数为2
新版本 的次数为1
吐血 的次数为1
检索 的次数为2
全文 的次数为1
常用 的次数为1
公用 的次数为1
分析器 的次数为1
项目 的次数为2
存储 的次数为1
数量词 的次数为1
处理器 的次数为1
工具包 的次数为1
占用 的次数为1
计数 的次数为1
分析 的次数为3
版本 的次数为1
正向 的次数为1
url 的次数为1
用了 的次数为2
迭代 的次数为1
搜索 的次数为1
模式 的次数为1
email 的次数为1
关键字 的次数为1
日期 的次数为1
扩展 的次数为1
提高 的次数为1
ikqueryparser 的次数为1
能力 的次数为1
3个 的次数为1
词典 的次数为3
排列组合 的次数为1
更小 的次数为1
定义 的次数为1
科学 的次数为1
高速 的次数为1
轻量级 的次数为1
优化 的次数为4
细粒度 的次数为1
2006年 的次数为1
发展为 的次数为1
多子 的次数为1
命中率 的次数为1
立于 的次数为1
数字 的次数为1
万字 的次数为1
60 的次数为1
特有 的次数为1
罗马数字 的次数为1
推出 的次数为2
用户 的次数为1
1.0版 的次数为1
ip 的次数为1
算法 的次数为3
分词 的次数为5
歧义 的次数为1
作者 的次数为1
java 的次数为2
语言 的次数为1
主体 的次数为1
最初 的次数为1
切分 的次数为1
排序后:================
lucene 的次数为5
分词 的次数为5
中文 的次数为4
这里面要注意一下,IK本身有一个文件叫IKAnalyzer.cfg.xml
这个文件可以自己配置词典,词典有两种分别是ext_dict及ext_stopwords,其中ext_dict主要定义了一些关键字,这些关键字不会被分词分开,ext_stopwords主要配置停止词,什么是停止词呢?比如“的”,“得”,“我”这些没有具体意义但是又出现特别多的词就不应该作为关键字词出现,所以在分词的时候要把这些词过滤掉。
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典-->
<entry key="ext_dict">ikdict/ext.dic;</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">ikdict/english_stopword.dic;ikdict/chinese_stopword.dic</entry>
</properties>
这里我主要配置了3个词典,其中的两个停止词分别是英文和中文的。网上有很多词典,但是都不是太全,我收集了一些,汇总了一下分享给大家。
但是OSC好像没有附件可以传。。。放到代码分享中了,用的自取,http://www.oschina.net/code/snippet_195637_22628
其中中文停止词4545个,英文停止词1434个,数据库相关词汇1692个。
总结一下,最近正在研究关键字及摘要自动生成,这里主要介绍了使用IK分词并统计词频,并分享了相关的词典。但是计算关键字单靠这样的分词统计词频还是不管用的,最近在研究TFIDF算法,后面实现成功了再和大家分享一下。