分词工具比较及使用(ansj、hanlp、jieba)
一、分词工具
ansj、hanlp、jieba
二、优缺点
1.ansj
优点:
提供多种分词方式
可直接根据内部词库分出人名、机构等信息
可构造多个词库,在分词时可动态选择所要使用的词库
缺点:
自定义词典时,系统词典还是被优先使用,导致词性不是自定义词典中的词性
多单词英文姓名无法分出
适用场景
若不使用自定义分词,可直接使用ansj
2.hanlp
优点:
自定义分词、词性方便
可分出多单词的英文名称(词典数据可带空格)
可动态增删词库,
动态添加词典前五千万速度很快,5m左右
缺点:
动态添加词典前五千万快的很,越往后越慢
词典文件添加自定义词典速度略慢,添加100w需要2m30s
适用场景:
词典数量少于五千万,词典数据若包含空格,用hanlp比较合适
3.jieba
优点:
自定义分词、词性方便
词典文件添加自定义词典比hanlp快,词典文件添加100w需要1m,八千万 2h多
缺点:
自定义词典时,带空格的词不支持
适用场景:
词典数量大于五千万
词典数据不能包含空格,否则分不出
ansj的使用
1.maven引入ansj包
<ansj.version>5.0.</ansj.version>
<tree_split.version>1.5</tree_split.version>
<nlp-lang.version>1.7.</nlp-lang.version> <!-- ansj_seg -->
<dependency>
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>${ansj.version}</version>
</dependency>
<!-- tree_split -->
<dependency>
<groupId>org.ansj</groupId>
<artifactId>tree_split</artifactId>
<version>${tree_split.version}</version>
</dependency>
<!-- nlp-lang -->
<dependency>
<groupId>org.nlpcn</groupId>
<artifactId>nlp-lang</artifactId>
<version>${nlp-lang.version}</version>
</dependency>
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", ""));
Forest dic2 = new Forest();
Library.insertWord(dic2, new Value("dota迷", "define", ""));
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", );
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<Term> 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<Term> 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="<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
String regEx_style="<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添加依赖
<dependency>
<groupId>com.hankcs</groupId>
<artifactId>hanlp</artifactId>
<version>portable-1.7.</version>
</dependency>
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<Term> terms = HanLP.segment(content);
Set<String> companySet = new HashSet<String>(); 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<String>(companySet));
logger.info("==== segment@分词结果:{},提取结果:{} ====", terms.toString(), segmentResult.toString());
return segmentResult;
}
5.自定义词典文件
词典文件格式如下,依次是 词、词性、权重
word nature weight
需要下载hanlp的data及hanlp.properties
https://github.com/hankcs/HanLP
data文件夹如下
hanlp.properties如下
#本配置文件中的路径的根目录,根目录+其他路径=完整路径(支持相对路径,请参考:https://github.com/hankcs/HanLP/pull/254)
#Windows用户请注意,路径分隔符统一使用/
root=/Users/FengZhen/Desktop/accumulate/分词/HanLP/ #好了,以上为唯一需要修改的部分,以下配置项按需反注释编辑。 #核心词典路径
#CoreDictionaryPath=data/dictionary/CoreNatureDictionary.txt
#2元语法词典路径
#BiGramDictionaryPath=data/dictionary/CoreNatureDictionary.ngram.txt
#自定义词典路径,用;隔开多个自定义词典,空格开头表示在同一个目录,使用“文件名 词性”形式则表示这个词典的词性默认是该词性。优先级递减。
#所有词典统一使用UTF-8编码,每一行代表一个单词,格式遵从[单词] [词性A] [A的频次] [词性B] [B的频次] ... 如果不填词性则表示采用词典的默认词性。
CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; Company.txt company; 现代汉语补充词库.txt; 全国地名大全.txt ns; 人名词典.txt; 机构名词典.txt; 上海地名.txt ns;data/dictionary/person/nrf.txt nrf;
#停用词词典路径
#CoreStopWordDictionaryPath=data/dictionary/stopwords.txt
#同义词词典路径
#CoreSynonymDictionaryDictionaryPath=data/dictionary/synonym/CoreSynonym.txt
#人名词典路径
#PersonDictionaryPath=data/dictionary/person/nr.txt
#人名词典转移矩阵路径
#PersonDictionaryTrPath=data/dictionary/person/nr.tr.txt
#繁简词典根目录
#tcDictionaryRoot=data/dictionary/tc
#HMM分词模型
#HMMSegmentModelPath=data/model/segment/HMMSegmentModel.bin
#分词结果是否展示词性
#ShowTermNature=true
#IO适配器,实现com.hankcs.hanlp.corpus.io.IIOAdapter接口以在不同的平台(Hadoop、Redis等)上运行HanLP
#默认的IO适配器如下,该适配器是基于普通文件系统的。
#IOAdapter=com.hankcs.hanlp.corpus.io.FileIOAdapter
#感知机词法分析器
#PerceptronCWSModelPath=data/model/perceptron/pku199801/cws.bin
#PerceptronPOSModelPath=data/model/perceptron/pku199801/pos.bin
#PerceptronNERModelPath=data/model/perceptron/pku199801/ner.bin
#CRF词法分析器
#CRFCWSModelPath=data/model/crf/pku199801/cws.txt
#CRFPOSModelPath=data/model/crf/pku199801/pos.txt
#CRFNERModelPath=data/model/crf/pku199801/ner.txt
#更多配置项请参考 https://github.com/hankcs/HanLP/blob/master/src/main/java/com/hankcs/hanlp/HanLP.java#L59 自行添加
注意:
1.hanlp.properties中的root路径为本地data文件夹的父级路径
2.准备好的词典文件可直接放入 data/dictionary/custom/下,然后再hanlp.properties中的 CustomDictionaryPath后添加该词典文件名即可,如果不想在词典文件中指定词性,也可在CustomDictionaryPath指定名字的同时,在后边空格指定词性。如上Company.txt company
3.在调用分词方法时,hanlp会去自动加载自定义添加的词典。速度比较慢,100w需要2m30s
4.自定义词典文件更新时,需要将data/dictionary/custom/CustomDictionary.txt.bin删掉。
Jieba的使用
1.环境准备
需要Python环境,需要pip
2.安装jieba
sudo pip install jieba
3.使用
# encoding=utf-
import jieba seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式 seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list)) # 精确模式 seg_list = jieba.cut("他来到了网易杭研大厦") # 默认是精确模式
print(", ".join(seg_list)) seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造") # 搜索引擎模式
print(", ".join(seg_list))
4.自定义词典
# encoding=utf-
import jieba
import jieba.posseg as pseg
import time print("start-time" + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
file_name = "/home/jenkins/fz/segment/jieba/data/Company.txt"
jieba.load_userdict(file_name) # file_name 为文件类对象或自定义词典的路径
print("end-time" + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) seg_list = jieba.cut("北京尚伯乐文化发展有限公司")
print("custom dic: " + "/ ".join(seg_list)) seg_list = pseg.cut(content) #带词性
for seg in seg_list:
print(seg)
词典内容如下
郑汴 company
灯塔市栈道村煤矿 company
深圳市莱斯达电信有限公司铁岭分公司 company
T&T ENERTECHNO company
MMI Holdings Ltd company
:三十门市部 company
关岭天利美容化妆品店 company
测试一下啦 company
分词工具比较及使用(ansj、hanlp、jieba)的更多相关文章
- 中文分词工具简介与安装教程(jieba、nlpir、hanlp、pkuseg、foolnltk、snownlp、thulac)
2.1 jieba 2.1.1 jieba简介 Jieba中文含义结巴,jieba库是目前做的最好的python分词组件.首先它的安装十分便捷,只需要使用pip安装:其次,它不需要另外下载其它的数据包 ...
- 中文分词工具探析(二):Jieba
1. 前言 Jieba是由fxsjy大神开源的一款中文分词工具,一款属于工业界的分词工具--模型易用简单.代码清晰可读,推荐有志学习NLP或Python的读一下源码.与采用分词模型Bigram + H ...
- 开源中文分词工具探析(三):Ansj
Ansj是由孙健(ansjsun)开源的一个中文分词器,为ICTLAS的Java版本,也采用了Bigram + HMM分词模型(可参考我之前写的文章):在Bigram分词的基础上,识别未登录词,以提高 ...
- Python分词工具——jieba
jieba简介 python在数据挖掘领域的使用越来越广泛.想要使用python做文本分析,分词是必不可少的一个环节在python的第三方包里,jieba应该算得上是分词领域的佼佼者. GitHub地 ...
- hanlp分词工具应用案例:商品图自动推荐功能的应用
本篇分享一个hanlp分词工具应用的案例,简单来说就是做一图库,让商家轻松方便的配置商品的图片,最好是可以一键完成配置的. 先看一下效果图吧: 商品单个推荐效果:匹配度高的放在最前面 这个想法很好,那 ...
- 中文分词工具——jieba
汉字是智慧和想象力的宝库. --索尼公司创始人井深大 简介 在英语中,单词就是"词"的表达,一个句子是由空格来分隔的,而在汉语中,词以字为基本单位,但是一篇文章的表达是以词来划分的 ...
- 中文分词工具探析(一):ICTCLAS (NLPIR)
1. 前言 ICTCLAS是张华平在2000年推出的中文分词系统,于2009年更名为NLPIR.ICTCLAS是中文分词界元老级工具了,作者开放出了free版本的源代码(1.0整理版本在此). 作者在 ...
- 开源中文分词工具探析(四):THULAC
THULAC是一款相当不错的中文分词工具,准确率高.分词速度蛮快的:并且在工程上做了很多优化,比如:用DAT存储训练特征(压缩训练模型),加入了标点符号的特征(提高分词准确率)等. 1. 前言 THU ...
- 开源中文分词工具探析(五):FNLP
FNLP是由Fudan NLP实验室的邱锡鹏老师开源的一套Java写就的中文NLP工具包,提供诸如分词.词性标注.文本分类.依存句法分析等功能. [开源中文分词工具探析]系列: 中文分词工具探析(一) ...
随机推荐
- 拼团商品列表页 分析 js代码行位置对执行的影响和window.onload的原理 setTimeout传参
w TypeError : Cannot set property 'innerHTML' of nullTypeError : Cannot set property 'value' of null ...
- 【转】spring boot application.properties 配置参数详情
multipart multipart.enabled 开启上传支持(默认:true) multipart.file-size-threshold: 大于该值的文件会被写到磁盘上 multipart. ...
- Apache 2.4 配置多个虚拟主机的问题
以前一直用Apache2.2的版本,最近升级到了2.4的版本,尝尝新版本嘛. 不过遇到了几个问题,一个就是配置了多个virtualhost,虽然没有报错,不过除了第一可以正常访问外,其他的都存在403 ...
- C#中Datatable和List互相转换
其实早就该写的,哈哈,不过今天刚想起来注册,热热手,就写一下,哈哈. 直接上内容吧: 建立一个控制台应用程序, List<students> Studentlist = new List& ...
- SpringBoot与Mybatis整合实例详解
介绍 从Spring Boot项目名称中的Boot可以看出来,SpringBoot的作用在于创建和启动新的基于Spring框架的项目,它的目的是帮助开发人员很容易的创建出独立运行的产品和产品级别的基于 ...
- mysql复习-来源考试
mysql复习- No1 .登录和权限 (一)常用命令1.登录mysqlmysql -h localhost -u root -p 2.重启mysqlservice mysql restart 延 ...
- JDK 注解详解
注解用途 我们在使用spring MVC框架时用到了很多的注解,如:@Controller.@RequestMapping等等,spring框架通过反射获取到标签进行不同的逻辑处理.注解是代码的附属信 ...
- 纯css,div隐藏滚动条,保留鼠标滚动效果。
示例1: html,body { height: 100%; } body { overflow: hidden; } .full-screen { position: relative; width ...
- 在Windows下使用Dev-C++开发基于pthread.h的多线程程序【转】
在Windows下使用Dev-C++开发基于pthread.h的多线程程序[转] 在Windows下使用Dev-C++开发基于pthread.h的多线程程序 文章分类:C++编程 ...
- 字符串的partition函数
partition函数 str1='sdga2a34'aa=str1.partition('a') print(aa) """ ('sdg', 'a', '2a34') ...