源码见:https://github.com/tangxing1993/lucene
什么是分词器
分词器,是将用户输入的一段文本,分析成符合逻辑的一种工具。
常用到分词器的类型
1. SimleAnalyzer
具备基本西文字符词汇分析的分词器,处理词汇单元时,以非字母字符作为分割符号。分词器不能做词汇的过滤,之进行词汇的分析和分割。输出地词汇单元完成小写字符转换,去掉标点符号等分割符。
2. StopAnalyzer
能过滤词汇中的特定字符串和词汇,并且完成大写转小写的功能。
3. WhitespaceAnalyzer
使用空格作为间隔符的词汇分割分词器。处理词汇单元的时候,以空格字符作为分割符号。分词器不做词汇过滤,也不进行小写字符转换。实际中可以用来支持特定环境下的西文符号的处理。由于不完成单词过滤和小写字符转换功能,也不需要过滤词库支持。词汇分割策略上简单使用非英文字符作为分割符,不需要分词词库支持。
4. StandardAnalyzer
根据空格和符号来完成分词,还可以完成数字、字母、E-mail地址、IP地址以及中文字符的分析处理,还可以支持过滤词表,用来代替StopAnalyzer能够实现的过滤功能。
5. IKAnalyzer
实现了以词典为基础的正反向全切分,以及正反向最大匹配切分两种方法。IKAnalyzer是第三方实现的分词器,继承自Lucene的Analyzer类,针对中文文本进行处理。
6. Paoding Analysis
Paoding Analysis中文分词具有极 高效率 和 高扩展性。引入隐喻,采用完全的面向对象设计,构思先进。其效率比较高,在PIII 1G内存个人机器上,1秒可准确分词100万汉字。采用基于不限制个数的词典文件对文章进行有效切分,使能够将对词汇分类定义。能够对未知的词汇进行合理解析。
7. MMSeg4J
mmseg4j 用 Chih-Hao Tsai 的 MMSeg 算法实现的中文分词器(http://technology.chtsai.org/mmseg/ ),并实现 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用。 MMSeg 算法有两种分词方法:Simple和Complex,都是基于正向最大匹配。Complex 加了四个规则过虑。官方说:词语的正确识别率达到了 98.41%。mmseg4j 已经实现了这两种分词算法。
分词流程
Analyzer是所有分词器的抽象父类,里面有一个public final TokenStream tokenStream(final String fieldName,final Reader reader) ,改方法把读入到的字符流处理成TokenStream单元。TokenStream有两个实现类Tokenizer和TokenFilter,Tokenizer把文本处理为分词单元(控制怎么分词),TokenFilter把过滤分词单元(控制保留那些分词),最后通过TokenStream完成索引。
TokenStreamAPI的流程
初始化TokenStream,TokenStream增加属性到AttributeSource
消费者调用reset()
消费者从TokenStream找属性,并把想要的值存放在本地变量中
消费者调用incrementToken直到返回false,每次调用后,消费属性值
消费者调用end(),执行流结束操作
/**
* Lucene分词器解析
* 分词器就是把给定的文本按照某种规则分解成最小词汇
* Analyzer是所有分词器的抽象父类
* TokenSteam是抽象父类中一个final方法,该方法用于把文本内容分解成最小单元SteamToken
* StreamToken是分解成的词汇单元,它有两个实现类Tokenizer和TokenFilter
* Tokenizer用于分解词汇单元
* TokenFilter用于过滤词汇单元
* StreamToken.incrementToken 判断是否还有下个词汇单元,属于生产者
* CharTermAttribute 词汇属性
* PositionIncrementAttribute 位置增量属性
* OffsetAttribute 偏移量属性
* TypeAttribute 分词类型属性
* @author tangx
*/
public class LuceneAnalyzer {
public static void main(String[] args){
displayTokenInfo("我是一个来自农村的中国人!", new StandardAnalyzer());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
displayTokenInfo("我是一个来自农村的中国人!", new MMSegAnalyzer());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
public static void displayTokenInfo(String text,Analyzer analyzer){
//获取词汇流
TokenStream stream = analyzer.tokenStream("", new StringReader(text));
//查看词汇属性
CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
//位置偏移量属性
PositionIncrementAttribute pia = stream.addAttribute(PositionIncrementAttribute.class);
//偏移量属性
OffsetAttribute oa = stream.addAttribute(OffsetAttribute.class);
//查看分词类型属性
TypeAttribute ta = stream.addAttribute(TypeAttribute.class);
try {
//重置下streamToken对象
stream.reset();
//判断是否还有下一个token
while(stream.incrementToken()){
System.out.println("TypeAttribute:"+ta+" | PositionIncrementAttribute:"+pia.getPositionIncrement()
+" | OffsetAttribute:["+oa.startOffset()+"-"+oa.endOffset()+"] | CharTermAttribute:"+cta
);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}