版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36059561/article/details/83404331
一、分词器的作用
分词器的作用就是得到一个TokenStream流,这个流中存储了分词相关的一些信息,可以通过属性获取到分词的详细信息。
二、自定义Stop分词器
package com.wsy;
import org.apache.lucene.analysis.*;
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.apache.lucene.util.Version;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Set;
public class MyStopAnalyzer extends Analyzer {
private Set set;
public MyStopAnalyzer(String[] stopWords) {
// 查看StopAnalyzer中的英文停用词
System.out.println(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
set = StopFilter.makeStopSet(Version.LUCENE_35, stopWords, true);
// 加入原来的停用词
set.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
}
public MyStopAnalyzer() {
set = StopAnalyzer.ENGLISH_STOP_WORDS_SET;
}
@Override
public TokenStream tokenStream(String fieldName, Reader reader) {
return new StopFilter(Version.LUCENE_35, new LowerCaseFilter(Version.LUCENE_35, new LetterTokenizer(Version.LUCENE_35, reader)), set);
}
public static void displayAllToken(String string, Analyzer analyzer) {
try {
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(string));
// 放入属性信息,为了查看流中的信息
// 位置增量信息,语汇单元之间的距离
PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class);
// 每个语汇单元的位置偏移量信息
OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
// 每一个语汇单元的分词信息
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
// 使用的分词器的类型信息
TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class);
while (tokenStream.incrementToken()) {
System.out.println(positionIncrementAttribute.getPositionIncrement() + ":" + charTermAttribute + "[" + offsetAttribute.startOffset() + "-" + offsetAttribute.endOffset() + "]-->" + typeAttribute.type());
}
System.out.println("----------------------------");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 自定义的停用词分词器
Analyzer analyzer1 = new MyStopAnalyzer(new String[]{"I", "you", "hate"});
// 默认的停用词分词器
Analyzer analyzer2 = new StopAnalyzer(Version.LUCENE_35);
String string = "how are you, thank you. I hate you.";
MyStopAnalyzer.displayAllToken(string, analyzer1);
MyStopAnalyzer.displayAllToken(string, analyzer2);
}
}
下面这条语句非常重要,用于给分词器设置过滤链和Tokenizer,如果还需要添加,继续向里面添加即可。
new StopFilter(Version.LUCENE_35, new LowerCaseFilter(Version.LUCENE_35, new LetterTokenizer(Version.LUCENE_35, reader)), set);
三、中文分词器
说道中文分词器,种类还是不少的,paoding分词,mmseg分词,IK分词等等。不过有些已经不更新了。
这里拿mmseg做演示,mmseg是基于搜狗的词库的,下载mmseg4j-1.8.5的压缩包。打开查看里面的内容,其中data中存放的是分词的词库,将jar包导入进项目,mmseg-all有两个jar包,一个是带dic的,一个是不带dic的,这里我们使用不带dic的。使用默认的分词词库测试了一下这样一段话“我来自山东聊城,我叫王劭阳。”,发现“聊城”被分成了“聊”和“城”,不服啊,竟然没有我大聊城?那么我们自己加上吧,打开data文件夹中的words-my.dic,添加上“聊城”,再次去看分词,“聊城”就会被分成“聊城”啦。
public static void main(String[] args) {
// mmseg分词器
// 没有指定分词库时候,一个字一个字的分词
Analyzer analyzer3 = new MMSegAnalyzer();
// 指定本地分词库后,根据分词器分词
Analyzer analyzer4 = new MMSegAnalyzer(new File("E:\\Lucene\\mmseg4j-1.8.5\\data"));
String string2 = "我来自山东聊城,我叫王劭阳。";
MyStopAnalyzer.displayAllToken(string2, analyzer3);
MyStopAnalyzer.displayAllToken(string2, analyzer4);
}