为ES构建Stanford NLP分词插件
Stanford NLP?
Stanford分词器是斯坦福大学NLP团队维护的一个开源分词器,支持了包括中文、英文…的语言,而且除了分词之外,它还支持了包括词性分析、情感分析…的各种功能。\ 这俩是这个project的项目主页
Why Stanford core NLP?
市面上确实会有很多很有名的开源分词器,比如IK、Jieba,还有一些其他团队和公司提供的开源/商用的分词器,他们各有优劣。但是在各种分词器上比较了一大堆的分词case之后,我们发现Stanford NLP似乎是最适合我们当前需求的一个,因为我们不仅仅需要分词,还需要一些包括情感分析之类在内的更多的一些功能。
我们公司是做金融数据的搜索推荐的,在对比了各家分词器之后我们老板觉得Stanford NLP的效果最好,但是作为算法出身的人,他实现了一套非常重的分词、排序、搜索的服务。
在对比如研报、财报之类的信息进行搜索的时候确实会比较有效,但是在对经济类的新闻进行搜索的时候就会显得十分的笨重。
基于这个背景,我开始试图在ES里面引入老板推崇的Stanford 分词器来适应他的搜索、分词的需要,同时也能够不通过他那个笨重的分词排序服务来对我们系统中大量的经济、金融类的新闻进行分词、索引,并提供和他自己分词效果类似的分词和检索服务。
Why this project
我在包括百度、某谷姓404网站、GitHub以及国内的中文社区(Elastic中文社区)在内的各种地方搜过也问过了,但是似乎没有一个直接开箱可用的分词插件。所以,我只剩一条路了,就是搭建一个自己的插件来引用这个分词器。
How
对ES来说,插件主要分为两个部分:
- 让ES可以看到的部分(class extends Plugin)
- 自己行使职能的部分(functional part)
plugin
- 为了让ES可以加载我们的plugin,我们需要先继承Plugin类,然后我们这个是个分词器插件,所以还要实现AnalysisPlugin类
- 看过ES源码或者其他分词器源码的同学应该会知道,分词器插件需要实现两个方法,一个用来提供tokenizer,一个是analyzer分别对应分词器中的这俩。
- 重写
Map<String, AnalysisModule.AnalysisProvider<TokenizerFactory>>
是为了可以提供搜索用分词器 - 重写
Map<String, AnalysisModule.AnalysisProvider<AnalyzerProvider<? extends Analyzer>>>
是为了可以提供索引用分词器
- 重写
- 在这个分词器里面我们主要是依靠Tokenizer来实现分词的
functional class
分词器,特别是Tokenizer主要是靠重写三个方法来实现分词的
- incrementToken:用来确定每一个词元,输出每一个单词(字)以及它的位置、长度等
- reset:用来重制分词结果
- end:用来告诉ES,这段文本的分词已经结束了
所以我们主要需要重写的就是这仨方法,当然了,为了能让分词器正确的使用,我们还需要添加一些分词器的配置和初始化的内容,具体代码不写了可以参考我的git,主要讲两个坑:
- ES是通过配置文件里的路径来寻找对应的插件类
- 然后通过配置文件里的key和刚才提到的代码里的key来寻找对应的分词器,所以这俩地方不要写错了
#plugin-descriptor.properties: classname=org.elasticsearch.plugin.analysis.AnalysisSDPlugin
#plugin-descriptor.properties: name=stanford-core-nlp
- 在开发过程中由于有java-security的存在,所以需要通过AccessController来调用和加载我们需要的外部jar包
odds and ends
- Stanford分词器里面包含了很多功能,目前我使用了分词的部分
- 分词器自带词典文件,不过如果要做词典的修改可能需要解包,修改,再重新打包
- 我现在hardcode了一大堆的标点符号在里面,后面可能会去优化一下部分逻辑
- 待完成的功能还有其他功能包括情感分析之类的
also see
本文地址:http://searchkit.cn/article/6341