Ik和Ansj分词器
背景
开发某项目,使用到websocket以及IK分词器,用户输入信息,根据用户输入的信息,进行拆分词,匹配数据库的关键词,符合关键词规则的返回数据。
分词器
- IK分词器
- Ansj分词器
IK分词器
开源地址
引入jar包
<dependency>
<groupId>com.github.magese</groupId>
<artifactId>ik-analyzer</artifactId>
<version>8.3.1</version>
</dependency>
代码实践
/**
* ik分词器
*
* @param custKeyword 输入词
* @return 关键词数组
*/
public String[] ikSolr(CustKeyword custKeyword) throws IOException {
String key = "";
Lexeme lexeme = null;
StringReader stringReader = new StringReader(custKeyword.getKeyword());
//第二个参数true;代表最大颗粒切分。false代表最细颗粒切分;
IKSegmenter ikSegmenter = new IKSegmenter(stringReader, false);
while ((lexeme = ikSegmenter.next()) != null) {
key += lexeme.getLexemeText() + ",";
}
key = key.substring(0, key.length() - 1);
String[] keywords = key.trim().split(",");
return keywords;
}
使用热更新自定义词词典进行分词
有时候我们对IK分词器系统默认词典并不满意,无法满足我们的实际项目需求。需要进行加入自定义词典才能满足需求。
例如,蚂蚁集团,IK分词器会拆分成“蚂蚁”和“集团”两组词语。如果不想拆开,就使用到了自定义词典了。用户配置的自定义词典内有“蚂蚁集团”,则IK分词器不会将这四个字拆开了。
网上的IK分词器大部分都是操作配置文件,不能满足我的实际需求。配置文件的缺点在于,一旦项目启动,配置文件中的自定义词也就确定了,后期就算新增了分词,新词也不会起作用。只能重启项目。
在项目中,我的需求是,需要加载数据库中配置的分词,IK分词器每次都要根据数据库中的自定义词进行分词。
代码
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.lucene.analysis.Analyzer;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.cfg.DefaultConfig;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import org.wltea.analyzer.dic.Dictionary;
import org.wltea.analyzer.lucene.IKAnalyzer;
/**
* LuceneHelper
* @author wwz
* @create 2019-08-28
*
*/
public class LuceneHelperUtils {
static Analyzer analyzer = new IKAnalyzer();
static Dictionary dictionary = null;
public static void init(){
Configuration cfg = DefaultConfig.getInstance(); //加载词库
cfg.setUseSmart(false); //true 用智能分词 ,false细粒度可以根根据可扩展词切词
Dictionary.initial(cfg);
dictionary = Dictionary.getSingleton();
}
/**
* 添加自定义词
* @param words
*/
public static void addCustomWords(Set<String>words){
dictionary.addWords(words);
}
/**
* 删除自定义词
* @param words
*/
public static void disableCustomWords(Set<String>words){
dictionary.disableWords(words);
}
public static List<String> queryWords(String query) {
List<String> list = new ArrayList<String>();
try {
StringReader input = new StringReader(query.trim());
// true 用智能分词 ,false细粒度可以根根据可扩展词切词
IKSegmenter ikSeg = new IKSegmenter(input, false);
for (Lexeme lexeme = ikSeg.next(); lexeme != null; lexeme = ikSeg.next()){
list.add(lexeme.getLexemeText());
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
public static void main(String[] args) {
init();
System.out.println(queryWords("养老证"));
Set<String> words = new HashSet<String>();
words.add("养老证");
addCustomWords(words);
disableCustomWords(words);
System.out.println(queryWords("养老证"));
}
/**
* 加入自定义词典后的分词方法
* @param keyword 输入词
*/
public String[] ikWords(String keyword) throws Exception {
init();
Set<String> words = new HashSet<String>();
//查询数据库所有分词
String allKeyWord = custKeyQuestionService.selectCustAllKeyword();
if (StringUtils.isNotEmpty(allKeyWord)) {
String[] keywordArr = allKeyWord.trim().split(",");
for (int x = 0; x < keywordArr.length; x++) {
words.add(keywordArr[x]);
}
}
addCustomWords(words);//添加自定义词
String key = "";
Lexeme lexeme = null;
StringReader stringReader = new StringReader(keyword.trim());
//第二个参数true;代表最大颗粒切分。false代表最细颗粒切分;
IKSegmenter ikSegmenter = new IKSegmenter(stringReader, false);
while ((lexeme = ikSegmenter.next()) != null) {
key += lexeme.getLexemeText() + ",";
}
key = key.substring(0, key.length() - 1);
System.out.println("分词结果=======================" + key);
String[] keywords = key.trim().split(",");
return keywords;
}
Ansj分词器
开源地址
引入jar包
<dependency>
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.1.6</version>
</dependency>
代码实践
/**
* Ansj分词器
*
* @param custKeyword 输入词
* @return 关键词数组
*/
public String[] ansjSolr(CustKeyword custKeyword) throws IOException {
String contentKeyword = NlpAnalysis.parse(custKeyword.getKeyword()).toStringWithOutNature();
String[] keywords = contentKeyword.trim().split(",");
return keywords;
}