在这一讲中,我们要看看Lucene到底是如何支持中文分词的?为了向大家阐述明白这个问题,咱们可先从分析器的执行过程入手。

分析器(Analyzer)的执行过程

如下图所示是语汇单元的生成过程:

从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Token。

要看分析器的分析效果,只需要看TokenStream中的内容就可以了。每个分析器都有一个tokenStream方法,返回的就是一个TokenStream对象。

标准分析器的分词效果

之前我们在创建索引库的时候,就用到了官方推荐的标准分析器,也就是org.apache.lucene.analysis.standard.StandardAnalyzer。现在,我们可以在一个单元测试类(比如FirstLucene.java)中编写一个如下的方法,来重新看看它的分词效果。

public class LuenceFirst {// 查看标准分析器的分词效果@Testpublic void testTokenStream() throws Exception {// 创建一个标准分析器对象Analyzer analyzer = new StandardAnalyzer();// 获得tokenStream对象// 第一个参数:域名,可以随便给一个// 第二个参数:要分析的文本内容TokenStream tokenStream = analyzer.tokenStream("test", "The Spring Framework provides a comprehensive programming and configuration model.");// 添加一个引用,可以获得每个关键词CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);// 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);// 将指针调整到列表的头部tokenStream.reset();// 遍历关键词列表,通过incrementToken方法判断列表是否结束while(tokenStream.incrementToken()) {// 关键词的起始位置System.out.println("start->" + offsetAttribute.startOffset());// 取关键词System.out.println(charTermAttribute);// 结束位置System.out.println("end->" + offsetAttribute.endOffset());}tokenStream.close();}}

这里我还是要说明一点,上述方法并不需要我们生写出来,因为它涉及到了C++语言方面的知识,所以说你不懂也没有问题,只须知道以上方法的作用是来查看标准分析器的分词效果的。运行以上方法,你将会在Eclipse控制台中看到如下打印内容。

从上图中我们可以清楚地看到当前的关键词,以及该关键词的起始位置和结束位置。

中文分析器分析

Lucene自带中文分词器


现在我们主要来看看第三个中文分析器的分词效果。相比较前两个中文分析器,SmartChineseAnalyzer绝对要胜出一筹。为了观看其分词效果,我们可将FirstLucene单元测试类中的testTokenStream方法改造为下面这个样子。

public class FirstLucene {// 查看智能中文分析器的分词效果@Testpublic void testTokenStream() throws Exception {Analyzer analyzer = new SmartChineseAnalyzer(); // 智能中文分析器// Analyzer analyzer = new IKAnalyzer();// 获得tokenStream对象// 第一个参数:域名,可以随便给一个// 第二个参数:要分析的文本内容TokenStream tokenStream = analyzer.tokenStream("test", "可以用二维表结构来逻辑表达实现的数据");// 添加一个引用,可以获得每个关键词CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);// 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);// 将指针调整到列表的头部tokenStream.reset();// 遍历关键词列表,通过incrementToken方法判断列表是否结束while(tokenStream.incrementToken()) {// 关键词的起始位置System.out.println("start->" + offsetAttribute.startOffset());// 取关键词System.out.println(charTermAttribute);// 结束位置System.out.println("end->" + offsetAttribute.endOffset());}tokenStream.close();}}

温馨提示:记得在工程中导入lucene-analyzers-smartcn-8.4.0.jar。运行以上方法,你将会在Eclipse控制台中看到如下打印内容。

虽然SmartChineseAnalyzer分析器对中文支持较好,但是扩展性差,扩展词库、禁用词库和同义词库等不好处理。故在实际开发中我们也是弃用的,取而代之的是第三方中文分析器。

第三方中文分析器

第三方中文分析器有很多,下面我会一一介绍到,虽然很多,但是大部分都已过时,用到的只是那一个而已,至于是哪一个,后面会揭晓。

paoding

庖丁解牛最新版在https://code.google.com/p/paoding/,其最多只支持Lucene 3.0,且最新提交的代码在2008-06-03,在svn中最新也是2010年提交,已经过时,不予考虑。

mmseg4j

最新版已从https://code.google.com/p/mmseg4j/移至https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代码是2014年6月,从09年~14年一共有18个版本,也就是一年几乎有3个大小版本,有较大的活跃度,用了mmseg算法。

IK-analyzer

最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10,从2006年12月推出1.0版开始,IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。但是也就在2012年12月后没有再更新了。

ansj_seg

最新版本在https://github.com/NLPchina/ansj_seg,tags仅有1.1版本,从2012年到2014年更新了大小6次,但是作者本人在2014年10月10日说明:“可能我以后没有精力来维护ansj_seg了”,现在由"nlp_china"管理。2014年11月有更新。并未说明是否支持Lucene,是一个由CRF(条件随机场)算法所做的分词算法。

imdict-chinese-analyzer

最新版在https://code.google.com/p/imdict-chinese-analyzer/,最新更新也在2009年5月,可下载源码,不支持Lucene 4.10。它利用的是HMM(隐马尔科夫链)算法。

Jcseg

最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,作者有较高的活跃度。其利用的是mmseg算法。

小结

虽然介绍了这么的第三方中文分析器,但是在这里,我使用的是IK-analyzer,所以下面的讲解也是围绕着该中文分析器来进行的。

IK-analyzer中文分析器的使用

如果你想要使用IK-analyzer,那么必然得下载其相关东西,例如jar包、核心配置文件以及扩展词典和停用词词典等。随着你使用的Lucene版本越来越高,相应地IK-analyzer的jar包的版本也要高一点才行,不然的话,就会有各种各样的问题,因为这些问题本人就碰到过。例如,由于本系列教程中所使用的Lucene是Lucene 8.4.0这个版本,所以我下载的就是ik-analyzer-7.6.0.jar这个jar包。

那么IK-analyzer中文分析器该怎么使用呢?IK-analyzer中文分析器的使用步骤如下:

  1. 把ik-analyzer-7.6.0.jar包添加到工程中;
  2. 把配置文件、扩展词典和停用词词典添加到classpath下。有一点需要注意:扩展词典和停用词词典这两个文件的字符集一定要保证是UTF-8字符集,注意是无BOM的UTF-8编码,严禁使用Windows的记事本编辑。

下面我们来看看IK-analyzer这个第三方中文分析器的分词效果。现在随着互联网的日趋发展,网络用语层出不穷,例如"高富帅","白富美"等等,像这样的网络用语是不需要进行分词的,而是当作一个整体的关键词,这样像这种不用分词的网络用语就应该存储在扩展词典中。为了清楚地观察IK-analyzer这个第三方中文分析器的分词效果,可以在扩展词典中添加"高富帅"这一网络用语,如下图所示。

然后将FirstLucene单元测试类中的testTokenStream方法改造为下面这个样子。

public class FirstLucene {// 查看第三方中文分析器的分词效果@Testpublic void testTokenStream() throws Exception {// 创建一个第三方中文分析器对象Analyzer analyzer = new IKAnalyzer();// 获得tokenStream对象// 第一个参数:域名,可以随便给一个// 第二个参数:要分析的文本内容TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据");// 添加一个引用,可以获得每个关键词CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);// 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);// 将指针调整到列表的头部tokenStream.reset();// 遍历关键词列表,通过incrementToken方法判断列表是否结束while(tokenStream.incrementToken()) {// 关键词的起始位置System.out.println("start->" + offsetAttribute.startOffset());// 取关键词System.out.println(charTermAttribute);// 结束位置System.out.println("end->" + offsetAttribute.endOffset());}tokenStream.close();}}

注意:千万要记得在IKAnalyzer.cfg.xml核心配置文件中配置好自己的扩展字典和停用词词典。

接着,运行以上方法,你将会在Eclipse控制台看到如下打印内容。

从上图可以清楚地看出"高富帅"这一网络用语并没有分词,这正是我们所期望的结果。

除此之外,对于一些敏感的词,如"安拉",像这样的敏感词汇就不应该出现在单词列表中,所以可将这种敏感词汇存储在停用词词典中,如下图所示。

然后将FirstLucene单元测试类中的testTokenStream方法改造为下面这个样子。

public class FirstLucene {// 查看第三方中文分析器的分词效果@Testpublic void testTokenStream() throws Exception {// 创建一个第三方中文分析器对象Analyzer analyzer = new IKAnalyzer();// 获得tokenStream对象// 第一个参数:域名,可以随便给一个// 第二个参数:要分析的文本内容TokenStream tokenStream = analyzer.tokenStream("test", "安拉,高富帅可以用二维表结构来逻辑表达实现的数据");// 添加一个引用,可以获得每个关键词CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);// 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);// 将指针调整到列表的头部tokenStream.reset();// 遍历关键词列表,通过incrementToken方法判断列表是否结束while(tokenStream.incrementToken()) {// 关键词的起始位置System.out.println("start->" + offsetAttribute.startOffset());// 取关键词System.out.println(charTermAttribute);// 结束位置System.out.println("end->" + offsetAttribute.endOffset());}tokenStream.close();}}

接着,运行以上方法,你将会在Eclipse控制台看到如下打印内容。

从上图可知,像"安拉"这样的敏感词汇并没有出现在单词列表中。

分析器的应用场景

索引时使用Analyzer

输入关键字进行搜索,当需要让该关键字与文档域内容所包含的词进行匹配时需要对文档域内容进行分析,需要经过Analyzer分析器处理生成语汇单元(Token)。分析器分析的对象是文档中的Field域。当Field的tokenized(是否分词)属性为true时会对Field值进行分析,如下图所示。

对于满足如下两点的一些Field可以不用分析:

  1. 不作为查询条件的内容,比如文件路径;
  2. 不是匹配内容中的词而匹配Field的整体内容,比如订单号、身份证号等。

搜索时使用Analyzer

对搜索关键字进行分析和索引分析一样,使用Analyzer对搜索关键字进行分析、分词处理,使用分析后的每个词语进行搜索。比如,搜索关键字spring web,经过分析器进行分词,得出spring web,拿词去索引词典表中查找,找到索引链接到Document,解析Document内容。

对于匹配整体Field域的查询可以在搜索时不分析,比如根据订单号、身份证号查询等。

小结

搜索使用的分析器要和索引使用的分析器保持一致(最好)。

Lucene快速入门第三讲——看看Lucene是如何支持中文分词的?相关推荐

  1. Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏 即使是现在,很多初学游戏开发的同学,在谈到Unity的时候,依然会认为Unity只能用于制作3D游戏的.实际上,Unity在2013年发布 ...

  2. 高一Python入门第三讲 石头剪刀布

    高一Python入门第三讲 石头剪刀布 专栏推荐 高一Python入门第一讲:播下一颗种子. 高一python入门第二讲 知人亦知面. 文章目录 高一Python入门第三讲 石头剪刀布 联系 3.1 ...

  3. 树莓派从零开始快速入门第8讲——单总线(以DS18B20为例)

    树莓派从零开始快速入门第8讲--单总线(以DS18B20为例) 目录 树莓派从零开始快速入门第8讲--单总线(以DS18B20为例) 一.前言 二.硬件连接 三.使能1-write接口 四.通讯测试 ...

  4. [猿来小课]Python开发入门第三讲:Python的安装

    今天猿来小课的老师给想要学习python开发语言的同学们讲一讲Python的安装,手把手带着大家完成学习python开发第一步.有条件的小伙伴跟着我一起来实战操作吧. 猿来Python开发入门第三讲: ...

  5. 树莓派从零开始快速入门第5讲——点亮LED

    树莓派从零开始快速入门第5讲--点亮LED 目录 树莓派从零开始快速入门第5讲--点亮LED 一.前言 二.引脚对照表 三.硬件连接 四.编写程序 1.编程方式简述 2.python编程 五.结束语 ...

  6. 树莓派从零开始快速入门第9讲——串口

    树莓派从零开始快速入门第9讲--串口 目录 树莓派从零开始快速入门第9讲--串口 一.前言 二.配置串口 三.串口收发测试 1.查询端口 2.串口调试 四.程序编写并运行 五.结束语 一.前言 串口是 ...

  7. 树莓派从零开始快速入门第14讲——摄像头

    树莓派从零开始快速入门第14讲--摄像头 目录 树莓派从零开始快速入门第14讲--摄像头 一.前言 二.硬件准备 三.软件配置 1.打开图形化窗口 2.下载并运行motion 3.查看监控画面 4.配 ...

  8. 树莓派从零开始快速入门第0讲——环境安装

    树莓派从零开始快速入门第0讲--环境安装 目录 树莓派从零开始快速入门第0讲--环境安装 一.前言 二.硬件准备 1. 树莓派(必选) 2. SD卡(必选) 3. 读卡器(必选) 4. 电源(必选) ...

  9. Lucene支持中文分词代码实现

    支持中文分词 分析器(Analyzer)的执行过程 如下图是语汇单元的生成过程: 从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语 ...

最新文章

  1. fiash星空动画制作_三维动画制作的详细流程
  2. How to use kingshard building a MySQL cluster
  3. Pywinauto 应用后端类型选择错误:AttributeError: ‘NoneType‘ object has no attribute ‘backend‘. 原因及解决办法
  4. Python动态类和动态方法的创建和调用
  5. Python教程:int数值类型的内置函数
  6. 【转】使用C#发送Http 请求实现模拟登陆(以博客园为例)
  7. iOS之从N个数里面取M个数的组合算法
  8. 程序异常异常代码: 0xc0000005_Java基础:看完这篇你还怕碰到异常吗?
  9. 我的Go+语言初体验——(5)Go+ 基本语法之 Switch
  10. 混合编程:如何用pybind11调用C++
  11. 2020 年微服务领域开源数字化报告发布,阿里扛起微服务大旗
  12. 信息时代大数据的再认识
  13. Python爬取起点中文网小说信息及封面图片
  14. php 生成导出excel,PHP导出生成EXCEL文件
  15. PDF转Word的免费软件推荐
  16. 什么是UV PV DAU MAU
  17. [ NeurIPS 2020 ] 一叶知秋 —— 基于“单目标域样本”的领域自适应方法
  18. win10怎么修复dns配置?DNS配置错误无法上网怎么解决
  19. 【VUE】图片预览放大缩小插件(推荐阅读)
  20. 16信号量(semaphore)

热门文章

  1. kubernetes运维笔记
  2. 学校人力资源管理系统可行性分析
  3. 预测分析:R语言实现2.3 多元线性回归
  4. abstract函数必须重写
  5. Keil5修改背景黑色仿VS
  6. go语言介绍和开发环境以及git使用
  7. mysql锁表、事务锁查询与杀死
  8. 发布!第五届“强网”拟态防御国际精英挑战赛精彩抢先看!
  9. iOS开发中常用的颜色及其对应的颜色值
  10. 信息系统项目管理师论文-项目范围管理