最近在做一个人工智能的项目,其中用到了分词功能。从网上找了一些java用于分词的工具,最终选择了ansj中文分词器。个人认为效果和功能是比较优秀的。本文将对ansj的所有功能进行详解并提供收集到的文本,下面开始正文:
引入如下maven依赖配置:
<!-- ansj分词插件依赖 -->
<dependency>
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.1.6</version>
</dependency>
看下面的测试类:
public static void main(String[] args) {
String str = "欢迎使用ansj_seg,(ansj中文分词)在这里如果你遇到什么问题都可以联系我.我一定尽我所能.帮助大家.ansj_seg更快,更准,更自由!" ;
Result result = ToAnalysis.parse(str); //分词结果的一个封装,主要是一个List<Term>的terms
System.out.println(result.getTerms());
List<Term> terms = result.getTerms(); //拿到terms
System.out.println(terms.size());
for(int i=0; i<terms.size(); i++) {
String word = terms.get(i).getName(); //拿到词
String natureStr = terms.get(i).getNatureStr(); //拿到词性
System.out.println(word + ":" + natureStr);
}
}
这个测试类说明了ansj的基本使用方法分为几下几步:
1、使用ToAnalysis.parse(str)将字符串进行分词,会返回一个Result,分词的结果就在它里面。
2、然后继续result.getTerms()获得分词结果的内容,因为是返回的多个分词,所以最终获得的是一个List。
3、然后遍历它,term.getName()获得的是词,term.getNatureStr()拿到的是这个词的词性。
测试最终结果如下:
欢迎:v
使用:v
ansj:en
_:null
seg:en
,:w
(:w
ansj:en
中文:nz
分词:v
):w
在:p
这里:r
如果:c
你:r
遇到:v
什么:r
问题:n
都:d
可以:v
联系:v
我:r
.:w
我:r
一定:d
尽:v
我:r
所能:v
.:w
帮助:v
大家:r
.:w
ansj:en
_:null
seg:en
更快:d
,:w
更:d
准:a
,:w
更:d
自由:a
!:w
从上面分词的结果可以看出有些词语我们本来是想让它放在一起的,但是分开了。因为ansj本身有一个词库,它是根据内部词库来进行分词的。但是内部词库也并不是那么完善,所以我们需要自己定义一个词库,在分词的时候把我们自己定义的词库加载进去,这样就可以达到我们预期的效果。
1、创建一个dic文件
在你电脑的任意位置创建一个名为userLibrary.dic的文件,内容如下:
尽我所能 v 1
更准 v 2
更自由 v 3
第一个是词语,第二个是词性,第三个是编号。词性这里大家不用关注,编号以此类推即可,不要重复。各个以缩进分隔。
2、加载自定义词库
你虽然已经定义了自定义词库,但是你还没有把它加入到你的ansj中去。看如下测试类:
public static void main(String[] args) {
// 关闭名字识别
MyStaticValue.isNameRecognition = false;
// 配置自定义词典的位置。注意是绝对路径
MyStaticValue.ENV.put(DicLibrary.DEFAULT,"D:\\ideaproject\\ocr\\src\\main\\resources\\userLibrary.dic");
String str = "欢迎使用ansj_seg,(ansj中文分词)在这里如果你遇到什么问题都可以联系我.我一定尽我所能.帮助大家.ansj_seg更快,更准,更自由!" ;
Result result = ToAnalysis.parse(str); //分词结果的一个封装,主要是一个List<Term>的terms
System.out.println(result.getTerms());
List<Term> terms = result.getTerms(); //拿到terms
System.out.println(terms.size());
for(int i=0; i<terms.size(); i++) {
String word = terms.get(i).getName(); //拿到词
String natureStr = terms.get(i).getNatureStr(); //拿到词性
System.out.println(word + ":" + natureStr);
}
}
我在前几行加入了加载自定义词库的代码,你只需要修改你自定义词库的路径即可,下面看测试结果:可以看到之前没有分出来的 ‘尽我所能’ 、‘更准’、‘更自由’ 由于我在自定义词库加入了它们所以成功分在一起了。
欢迎:v
使用:v
ansj:en
_:null
seg:en
,:w
(:w
ansj:en
中文:nz
分词:v
):w
在:p
这里:r
如果:c
你:r
遇到:v
什么:r
问题:n
都:d
可以:v
联系:v
我:r
.:w
我:r
一定:d
尽我所能:v
.:w
帮助:v
大家:r
.:w
ansj:en
_:null
seg:en
更快:d
,:w
更准:v
,:w
更自由:v
!:w
大家要知道停用词是什么,就是当我们使用ansj将一句话分词的时候,它分出来的词语会有一些没有任何意义的词,最近我在做的是语义分析,这些词是会影响语义分析结果的,所以必须将其去掉。比如 ‘啊’、‘嗯’、‘哦’等词。创建停用词库步骤如下:
1、创建一个dic文件
在你电脑的任意位置创建一个名为stopLibrary.dic的文件,内容如下:
啊
阿
哎
唉
俺
按
吧
直接写停用词,每一行写一个。
2、加载自定义词库
直接看如下代码,手写酸了。。。。。
public static void main(String[] args) {
// 关闭名字识别
MyStaticValue.isNameRecognition = false;
// 配置自定义词典的位置。注意是绝对路径
MyStaticValue.ENV.put(DicLibrary.DEFAULT,"D:\\ideaproject\\ocr\\src\\main\\resources\\userLibrary.dic");
//去停用词
List<String> stopWords = getStopWords("D:\\ideaproject\\ocr\\src\\main\\resources\\library\\stopLibrary.dic");
StopRecognition filter = new StopRecognition();
filter.insertStopWords(stopWords);
String str = "欢迎使用ansj_seg,(ansj中文分词)在这里如果你遇到什么问题都可以联系我.我一定尽我所能.帮助大家.ansj_seg更快,更准,更自由!" ;
Result result = ToAnalysis.parse(str).recognition(filter); //分词结果的一个封装,主要是一个List<Term>的terms
System.out.println(result.getTerms());
List<Term> terms = result.getTerms(); //拿到terms
System.out.println(terms.size());
for(int i=0; i<terms.size(); i++) {
String word = terms.get(i).getName(); //拿到词
String natureStr = terms.get(i).getNatureStr(); //拿到词性
System.out.println(word + ":" + natureStr);
}
}
注意看去停用词那块,就是将停用词库的内容获取放到List中然后加入到ansj的停用词库中。还有在分词时ToAnalysis.parse(str).recognition(filter)加入了.recognition(filter)这个,它就是将你停用词库加入到ansj中去。这里我用到了一个getStopWords方法,参数就是你自定义停用词库的路径,内容如下:
private static List<String> getStopWords(String url){
// 使用一个字符串集合来存储文本中的路径 ,也可用String []数组
List<String> list = new ArrayList<String>();
try {
FileInputStream fis = new FileInputStream(url);
// 防止路径乱码 如果utf-8 乱码 改GBK eclipse里创建的txt 用UTF-8,在电脑上自己创建的txt 用GBK
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null) {
// 如果 t x t文件里的路径 不包含---字符串 这里是对里面的内容进行一个筛选
if (line.lastIndexOf("---") < 0) {
list.add(line);
}
}
br.close();
isr.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
3、测试结果
不测试了,手真的酸了。但是这里要说一个小细节,就是去停用词是在分词后,而不是分词前。
直接看这篇吧,写的挺好。https://blog.csdn.net/lb521200200/article/details/53696387
如果对这几种模式还是不太理解,或者觉得这篇博文讲的太官方了,欢迎给我留言
另外给大家提供搜狗词库去重两百万词库。
链接:https://pan.baidu.com/s/1CJVOTVwDkbkFkIueBKjgtw
提取码:3fnn