初识IKAnalyzer
package com.sunmap.analyzer; import java.io.IOException; import java.io.StringReader; import org.wltea.analyzer.core.IKSegmenter; import org.wltea.analyzer.core.Lexeme; /** *IK分词器核心 * *大体流程: * *1.待分词的字符串 *2.创建分词器对象进行分词(在分词之前先加载词库) *3.分词完成以后会得到分词后的流,然后一一遍历出来 */ public class IKSegmenterTest { public static void main(String[] args) { String text = "黑河:边防官兵零下20余度严寒“摆兵布阵” 如猛虎下山血性十足"; //执行这段代码时,会去加载词库 //true 代表是否使用只能分词;false 代表细粒度分词 IKSegmenter iKSegmenter = new IKSegmenter(new StringReader(text), true); Lexeme lexeme = null; try { //分词,获取下一个词元 while((lexeme = iKSegmenter.next()) != null){ System.out.println(lexeme.toString()); } } catch (IOException e) { e.printStackTrace(); } } }
输出结果:
加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
0-2 : 黑河 : CN_WORD
3-5 : 边防 : CN_WORD
5-7 : 官兵 : CN_WORD
7-9 : 零下 : CN_WORD
9-11 : 20 : ARABIC
11-12 : 余 : CN_CHAR
12-13 : 度 : CN_CHAR
13-15 : 严寒 : CN_WORD
16-17 : 摆 : CN_CHAR
17-18 : 兵 : CN_CHAR
18-20 : 布阵 : CN_WORD
22-23 : 如 : CN_CHAR
23-27 : 猛虎下山 : CN_WORD
27-29 : 血性 : CN_WORD
29-31 : 十足 : CN_WORD
下面说一下加载词库:
package com.sunmap.analyzer; import org.wltea.analyzer.cfg.Configuration; import org.wltea.analyzer.cfg.DefaultConfig; public class DefaultConfigTest { /** * Configuration词库的配置管理类 * * IKAnalyzer分词器有自己的词库,在org/wltea/analyzer/dic/main2012.dic * 量词词库:org/wltea/analyzer/dic/quantifier.dic * * 获取扩展字典配置路径:[ext.dic] 如果提供的词库没有我们想要的可以加在这个文件里 * 获取扩展停止词典配置路径:[stopword.dic] 同理~ * * * */ public static void main(String[] args) { Configuration defaultConfig = DefaultConfig.getInstance(); System.out.println(" 获取主词典路径:"+defaultConfig.getMainDictionary()); System.out.println("获取量词词典路径:"+defaultConfig.getQuantifierDicionary()); System.out.println("获取扩展字典配置路径:"+defaultConfig.getExtDictionarys()); System.out.println("获取扩展停止词典配置路径:"+defaultConfig.getExtStopWordDictionarys()); } }
接下来说一下如何自己写一个分词器类:
package com.sunmap.analyzer; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.analysis.tokenattributes.TypeAttribute; import org.wltea.analyzer.lucene.IKTokenizer; /** * 自己实现IK分词器 * * 分词器的核心类Analyzer,TokenStream,Tokenizer,TokenFilter. * Analyzer:Lucene中的分词器有StandardAnalyzer, StopAnalyzer,SimpleAnalyzer,WhitespaceAnalyzer * TokenStream:分词器做好处理之后得到的一个流,这个流中存储了分词的各种信息.可以通过TokenStream有效的获取到分词单元 * Tokenizer:主要负责接收字符流Reader,将Reader进行分词操作. * TokenFilter:将分好词的语汇单元进行各种各样的过滤. * */ public class MyAnalyzer extends Analyzer{ /* * 分词类的大体流程: * 1.首先要写一个继承自Analyzerde的类,即:MyAnalyzer * 2.MyAnalyzer对象调用tokenStream(String str,Reader reader)方法时该方法会调用createComponents(String arg0, Reader arg1)方法, * createComponentsfan方法是继承Analyzer类必须要重写的方法,也就是你要创建什么样类型的分词类; * * tokenStream(String str,Reader reader)在调用时,里面有将分好词的语汇单元进行各种各样的过滤. * * */ @Override protected TokenStreamComponents createComponents(String arg0, Reader arg1) { System.out.println("----------createComponents------------"); //这块我们采用的还是IK分词机制,如果想写别的分词,就创建别的对象 return new TokenStreamComponents(new IKTokenizer(arg1, true)); } public static void main(String[] args) { MyAnalyzer myAnalyzer = new MyAnalyzer(); String text = "2016年是小米的关键年,处于势能与舆论是否转向的关键时期,是持续调整还是能扭转态势,乐观的认为触底反弹,悲观的认为大势已去,属于小米的时代已经过去。小米还有招吗,还能迎来第二春吗?14"; try { // // 将一个字符串创建成Token流,第一个参数没啥用处 TokenStream tokenStream = myAnalyzer.tokenStream("1111", new StringReader(text)); // 获取词与词之间的位置增量 PositionIncrementAttribute postiona = tokenStream.addAttribute(PositionIncrementAttribute.class); // 获取各个单词之间的偏移量 OffsetAttribute offseta = tokenStream.addAttribute(OffsetAttribute.class); // 获取每个单词信息(保存相应词汇) CharTermAttribute chara = tokenStream.addAttribute(CharTermAttribute.class); // 获取当前分词的类型 TypeAttribute typea = tokenStream.addAttribute(TypeAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()) { System.out.print("位置增量" +postiona.getPositionIncrement()+":\t"); System.out.println(chara+"\t[" + offseta.startOffset()+" - " + offseta.endOffset() + "]\t<" + typea.type() +">"); } } catch (IOException e) { e.printStackTrace(); } } }
输出结果:
----------createComponents------------
加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
位置增量1: 2016年 [0 - 5] <TYPE_CQUAN>
位置增量1: 小米 [6 - 8] <CN_WORD>
位置增量1: 关键 [9 - 11] <CN_WORD>
位置增量1: 处于 [13 - 15] <CN_WORD>
位置增量1: 势 [15 - 16] <CN_CHAR>
位置增量1: 能与 [16 - 18] <CN_WORD>
位置增量1: 舆论 [18 - 20] <CN_WORD>
位置增量1: 是否 [20 - 22] <CN_WORD>
位置增量1: 转向 [22 - 24] <CN_WORD>
位置增量1: 关键时期 [25 - 29] <CN_WORD>
位置增量1: 持续 [31 - 33] <CN_WORD>
位置增量1: 调整 [33 - 35] <CN_WORD>
位置增量1: 还是 [35 - 37] <CN_WORD>
位置增量1: 能 [37 - 38] <CN_CHAR>
位置增量1: 扭转 [38 - 40] <CN_WORD>
位置增量1: 态势 [40 - 42] <CN_WORD>
位置增量1: 乐观 [43 - 45] <CN_WORD>
位置增量1: 认为 [46 - 48] <CN_WORD>
位置增量1: 触底 [48 - 50] <CN_WORD>
位置增量1: 反弹 [50 - 52] <CN_WORD>
位置增量1: 悲观 [53 - 55] <CN_WORD>
位置增量1: 认为 [56 - 58] <CN_WORD>
位置增量1: 大势已去 [58 - 62] <CN_WORD>
位置增量1: 属于 [63 - 65] <CN_WORD>
位置增量1: 小米 [65 - 67] <CN_WORD>
位置增量1: 时代 [68 - 70] <CN_WORD>
位置增量1: 已经 [70 - 72] <CN_WORD>
位置增量1: 过去 [72 - 74] <CN_WORD>
位置增量1: 小米 [75 - 77] <CN_WORD>
位置增量1: 还有 [77 - 79] <CN_WORD>
位置增量1: 招 [79 - 80] <CN_CHAR>
位置增量1: 还能 [82 - 84] <CN_WORD>
位置增量1: 迎来 [84 - 86] <CN_WORD>
位置增量1: 第二 [86 - 88] <CN_WORD>
位置增量1: 春 [88 - 89] <CN_CHAR>
位置增量1: 14 [91 - 93] <ARABIC>