Java分词器比较(ansj、hanlp、ik)

Java分词器比较(ansj、hanlp、ik)

Java分词器比较(ansj、hanlp、ik)

一、分词工具

ansj

hanlp

ik

分词准确性排行:hanlp > ansj > 结巴 > IK > Smart Chinese Analysis

二、优缺点

1.ansj

优点:

1. 提供多种分词方式

2. 可直接根据内部词库分出人名、机构等信息

3. 可构造多个词库,在分词时可动态选择所要使用的词库

缺点:

1. 自定义词典时,系统词典还是被优先使用,导致词性不是自定义词典中的词性

2. 多单词英文姓名无法分出

3. 对标hanlp词库略少,学习成本高

适用场景

1. 若不使用自定义分词,可直接使用ansj

2.hanlp

优点:

1. 自定义分词、词性方便

2. 可分出多单词的英文名称(词典数据可带空格)

3. 可动态增删词库,

4. 动态添加词典前五千万速度很快,5m左右

缺点:

1. 动态添加词典前五千万快的很,越往后越慢

2. 词典文件添加自定义词典速度略慢,添加100w需要2m30s

适用场景:

1. 词典数量少于五千万,词典数据若包含空格,用hanlp比较合适

3.IKanalyzer

优点:

1. 开源、轻量、

2. 支持自定义词典和远程词典

3. bug少,稳定,简单易用。

缺点:

1. 不够智能,

2. 词库需要自行维护

3. 不支持词性识别

适用场景:

1. 词典数量少于五千万,词典数据若包含空格,用hanlp比较合适

总结

对搜索要求不高的建议选用 IK 学习成本低,使用教程多,还支持远程词典

Ansj和hanlp均基于自然处理语言,分词准确度高,活跃度来讲hanlp略胜一筹

ansj的使用

1.maven引入ansj包

5.0.4

1.5

1.7.7

org.ansj

ansj_seg

${ansj.version}

org.ansj

tree_split

${tree_split.version}

org.nlpcn

nlp-lang

${nlp-lang.version}

2.在项目根目录下创建library文件夹,文件夹下包括以下几个词典文件(自行添加)

ambiguity.dic

default.dic

userLibrary.dic

3.使用

package com.zhen.segment;

import java.io.InputStream;

import java.util.List;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.ansj.domain.Result;

import org.ansj.domain.Term;

import org.ansj.library.UserDefineLibrary;

import org.ansj.splitWord.analysis.BaseAnalysis;

import org.ansj.splitWord.analysis.NlpAnalysis;

import org.ansj.splitWord.analysis.ToAnalysis;

import org.nlpcn.commons.lang.tire.domain.Forest;

import org.nlpcn.commons.lang.tire.domain.Value;

import org.nlpcn.commons.lang.tire.library.Library;

/**

* @author FengZhen

* @date Jan 30, 2019

* ansj分词

*/

public class SegmentTest {

public static void main(String[] args) {

// dynamicWord();

// localDic();

// moreUserDic();

}

/**

* 多用户词典(新增、删除)

*/

public static void moreUserDic() {

// 多用户词典

String str = "神探夏洛克这部电影作者.是一个dota迷";

System.out.println(ToAnalysis.parse(str));

// 两个词汇 神探夏洛克 douta迷

Forest dic1 = new Forest();

Library.insertWord(dic1, new Value("神探夏洛克", "define", "1000"));

Forest dic2 = new Forest();

Library.insertWord(dic2, new Value("dota迷", "define", "1000"));

System.out.println(ToAnalysis.parse(str, dic1, dic2));

System.out.println("-------删除dic1中的词");

Library.removeWord(dic1, "神探夏洛克");

System.out.println(ToAnalysis.parse(str, dic1, dic2));

}

/**

* 动态增删词库

*/

public static void dynamicWord(){

// 增加新词,中间按照'\t'隔开

UserDefineLibrary.insertWord("ansj中文分词", "userDefine", 1000);

Result result = ToAnalysis.parse("我觉得Ansj中文分词是一个不错的系统!我是王婆!");

System.out.println("增加新词例子:" + result);

// 删除词语,只能删除.用户自定义的词典.

UserDefineLibrary.removeWord("ansj中文分词");

result = ToAnalysis.parse("我觉得ansj中文分词是一个不错的系统!我是王婆!");

System.out.println("删除用户自定义词典例子:" + result);

//将用户自定义词典清空

UserDefineLibrary.clear();

}

/**

* 加载词典文件

*/

public static void localDic(){

try {

//读的是根目录下的

Forest rootForest = Library.makeForest("library/userLibrary.dic");

System.out.println(rootForest.toMap());

//加载字典文件,取的是resource下的

InputStream inputStream = SegmentTest.class.getResourceAsStream("/library/userLibrary.dic");

Forest resoutceForest=Library.makeForest(inputStream);

String str = "我觉得ansj中文分词是一个不错的系统!我是王婆!";

Result result=ToAnalysis.parse(str, resoutceForest);//传入forest

List termList=result.getTerms();

for(Term term:termList){

System.out.println(term.getName()+":"+term.getNatureStr());

}

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 基本分词

* 基本就是保证了最基本的分词.词语颗粒度最非常小的..所涉及到的词大约是10万左右.

* 基本分词速度非常快.在macAir上.能到每秒300w字每秒.同时准确率也很高.但是对于新词他的功能十分有限

* @param content

*/

public static void baseAnay(String content) {

Result result = BaseAnalysis.parse(delHTMLTag(content).replace("\n","").replace(" ", "").replace("\t",""));

System.out.println("result:" + result);

}

/**

* 精准分词

* 它在易用性,稳定性.准确性.以及分词效率上.都取得了一个不错的平衡.

* @param content

*/

public static void toAnay(String content){

Result result = ToAnalysis.parse(content);

System.out.println("result:" + result);

}

/**

* nlp分词(单条新闻处理7秒)

* 可以识别出未登录词.但是它也有它的缺点.速度比较慢.稳定性差.ps:我这里说的慢仅仅是和自己的其他方式比较.应该是40w字每秒的速度吧.

* 个人觉得nlp的适用方式.1.语法实体名抽取.未登录词整理.只要是对文本进行发现分析等工作

* 会把企业分开

* @param content

*/

public static void nlpAnay(String content){

Result result = NlpAnalysis.parse(delHTMLTag(content).replace("\n","").replace(" ", "").replace("\t",""));

System.out.println("result:" + result);

List terms = result.getTerms();

for (Term term : terms) {

String name = term.getName();

String nature = term.getNatureStr();

if (nature.equals("nt") || nature.equals("nr")) {

System.out.println("------------------");

System.out.println("getName:" + term.getName());

System.out.println("getNatureStr:" + term.getNatureStr());

}

}

}

/**

* 筛除HTML标签

* @param htmlStr

* @return

*/

public static String delHTMLTag(String htmlStr){

String regEx_script="]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式

String regEx_style="]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式

String regEx_html="<[^>]+>"; //定义HTML标签的正则表达式

Pattern p_script=Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE);

Matcher m_script=p_script.matcher(htmlStr);

htmlStr=m_script.replaceAll(""); //过滤script标签

Pattern p_style=Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE);

Matcher m_style=p_style.matcher(htmlStr);

htmlStr=m_style.replaceAll(""); //过滤style标签

Pattern p_html=Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE);

Matcher m_html=p_html.matcher(htmlStr);

htmlStr=m_html.replaceAll(""); //过滤html标签

return htmlStr.trim(); //返回文本字符串

}

}

hanlp的使用

1.maven添加依赖

com.hankcs

hanlp

portable-1.7.1

2.动态添加词

/**

* 新增词

*/

public static void addWord(String word, NatureEnum nature) {

logger.info("==== addWord@word:{},nature:{},weight:{} ====", word, nature.getNature(), nature.getWeight());

if (!StringUtils.isBlank(word) && !word.equals("null")) {

//大小括号问题

if (word.contains("(") || word.contains(")")) {

CustomDictionary.insert(word.replace("(", "(").replace(")", ")"), nature.getNature());

}else if (word.contains("(") || word.contains(")")) {

CustomDictionary.insert(word.replace("(", "(").replace(")", ")"), nature.getNature());

}

CustomDictionary.insert(word, nature.getNature());

}else {

logger.warn("==== addWord@ word({})为空 ====", word);

}

}

3.动态删除词

/**

* 删除词

* @param forest

* @param word

*/

public static void deleteWord(String word) {

logger.info("==== deleteWord@word:{} ====", word);

if (!StringUtils.isBlank(word)) {

CustomDictionary.remove(word);

}else {

logger.warn("==== deleteWord@word为空({}) ====", word);

}

}

4.使用

/**

* 分词

* @param content

* @param forests

* ToAnalysis精准分词

* BaseAnalysis基础分词

*/

public static SegmentResult segment(String content) {

logger.info("==== segment@content:{} ====", content);

SegmentResult segmentResult = new SegmentResult();

List terms = HanLP.segment(content);

Set companySet = new HashSet();

for (Term term : terms) {

String name = term.word;

String nature = term.nature.toString();

if (nature.equals(NatureEnum.Company.getNature())) {

companySet.add(name);

}

}

segmentResult.setCompanys(new ArrayList(companySet));

logger.info("==== segment@分词结果:{},提取结果:{} ====", terms.toString(), segmentResult.toString());

return segmentResult;

}

5.自定义词典文件

词典文件格式如下,依次是 词、词性、权重

word nature weight

需要下载hanlp的data及hanlp.properties

https://github.com/hankcs/HanLP

data文件夹如下

ik分词器

依赖

com.janeluo

ikanalyzer

2012_u6

org.apache.lucene

lucene-core

org.apache.lucene

lucene-queryparser

org.apache.lucene

lucene-analyzers-common

org.apache.lucene

lucene-queryparser

7.3.0

使用

/**

* 分词器(可能比较耗时)

*

* @param content str

* @return java.util.List

* @author ext.wenzhongming1

* @since 2023/2/28 14:18

*/

public static List iKSegToList(String content) {

content = clearHtmlTag(content);

List list = new ArrayList<>();

try {

if (StringUtils.isEmpty(content)) {

return Lists.newArrayList();

}

StringReader sr = new StringReader(content);

// 关闭智能分词 (对分词的精度影响较大)

IKSegmenter ik = new IKSegmenter(sr, false);

Lexeme lex;

while ((lex = ik.next()) != null) {

String lexemeText = lex.getLexemeText();

list.add(lexemeText);

}

} catch (Exception e) {

log.error("分词异常");

}

return list;

}

public static void main(String[] args) {

// ik 切词

String content = "https://www.relaxheart.cn 是xx同学的个人兴趣分享网站";

System.out.println(iKSegToList(content));

}

输出

加载扩展词典:extend.dic

加载扩展停止词典:stopword.dic

[https, www.relaxheart.cn, www, relaxheart, cn, 是, xx, 同学, 个人兴趣, 个人, 兴趣, 分享, 网站]

相关推荐

862 區域電話號碼:位置、優勢和主要見解
dnf起源版本缔造者荒古扫把刷图加点
时代峰峻训练生底薪8000元?回应:无底薪!都是课余训练
涮字笔画写法