Lucene(6):分词器

news2024/11/24 2:27:33

1 分词理解

在对Document中的内容进行索引之前,需要使用分词器进行分词 ,分词的目的是为了搜索。分词的主要过程就是先分词后过滤。

  • 分词:采集到的数据会存储到document对象的Field域中,分词就是将Document中Field的value值切分成一个一个的词。
  • 过滤:包括去除标点符号过滤、去除停用词过滤(的、是、a、an、the等)、大写转小写、词的形还原(复数形式转成单数形参、过去式转成现在式。。。)等。

什么是停用词?停用词是为节省存储空间和提高搜索效率,搜索引擎在索引页面或处理搜索请求时会自动忽略某些字或词,这些字或词即被称为Stop Words(停用词)。比如语气助词、副词、介词、连接词等,通常自身并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”、“是”、“啊”等。

对于分词来说,不同的语言,分词规则不同。Lucene作为一个工具包提供不同国家的分词器

2 Analyzer使用时机

2.1 索引时使用Analyzer

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

对于一些Field可以不用分析:

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

2.2 搜索时使用Analyzer

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

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

注意:搜索使用的分析器要和索引使用的分析器一致。

3 Lucene原生分词器

以下是Lucene中自带的分词器

3.1 StandardAnalyzer

特点 :Lucene提供的标准分词器, 可以对用英文进行分词, 对中文是单字分词, 也就是一个字就认为是一个词.

如下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源码:

protected TokenStreamComponents createComponents(String fieldName) {
    final StandardTokenizer src = new StandardTokenizer();
    src.setMaxTokenLength(this.maxTokenLength);
    TokenStream tok = new LowerCaseFilter(src);
    TokenStream tok = new StopFilter(tok, this.stopwords);
    return new TokenStreamComponents(src, tok) {
        protected void setReader(Reader reader) {
            src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
            super.setReader(reader);
        }
    };
}

Tokenizer就是分词器,负责将reader转换为语汇单元即进行分词处理,Lucene提供了很多的分词器,也可以使用第三方的分词,比如IKAnalyzer一个中文分词器。

TokenFilter是分词过滤器,负责对语汇单元进行过滤,TokenFilter可以是一个过滤器链儿,Lucene提供了很多的分词器过滤器,比如大小写转换、去除停用词等。

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

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

比如下边的文档经过分析器分析如下:

原文档内容:

 

分析后得到的多个语汇单元:

3.2 WhitespaceAnalyzer

特点 :仅仅是去掉了空格,没有其他任何操作,不支持中文。

测试代码:

    @Test
    public void TestWhitespaceAnalyzer() throws Exception{
        // 1. 创建分词器,分析文档,对文档进行分词
        Analyzer analyzer = new WhitespaceAnalyzer();
        // 2. 创建Directory对象,声明索引库的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\dir"));
        // 3. 创建IndexWriteConfig对象,写入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter写入对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        // 5.写入到索引库,通过IndexWriter添加文档对象document
        Document doc = new Document();
        doc.add(new TextField("name", "vivo X23 8GB+128GB 幻夜蓝", Field.Store.YES));
        indexWriter.addDocument(doc);
        // 6.释放资源
        indexWriter.close();
    }

结果:

3.3 SimpleAnalyzer

特点 :

将除了字母以外的符号全部去除,并且将所有字母变为小写,需要注意的是这个分词器同样把数字也去除了,同样不支持中文。

测试:

    @Test
    public void TestSimpleAnalyzer() throws Exception{
        // 1. 创建分词器,分析文档,对文档进行分词
        Analyzer analyzer = new SimpleAnalyzer();
        // 2. 创建Directory对象,声明索引库的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\dir"));
        // 3. 创建IndexWriteConfig对象,写入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter写入对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        // 5.写入到索引库,通过IndexWriter添加文档对象document
        Document doc = new Document();
        doc.add(new TextField("name", "vivo,X23。 8GB+128GB; 幻夜蓝",
                Field.Store.YES));
        indexWriter.addDocument(doc);
        // 6.释放资源
        indexWriter.close();
    }

结果:

3.4 CJKAnalyzer

特点 :

这个支持中日韩文字,前三个字母也就是这三个国家的缩写。对中文是二分法分词, 去掉空格, 去掉标点符号。个人感觉对中文支持依旧很烂。

代码:

    @Test
    public void TestCJKAnalyzer() throws Exception{
        // 1. 创建分词器,分析文档,对文档进行分词
        Analyzer analyzer = new CJKAnalyzer();
        // 2. 创建Directory对象,声明索引库的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\dir"));
        // 3. 创建IndexWriteConfig对象,写入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter写入对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        // 5.写入到索引库,通过IndexWriter添加文档对象document
        Document doc = new Document();
        doc.add(new TextField("name", "vivo,X23。 8GB+128GB; 幻夜蓝",
                Field.Store.YES));
        indexWriter.addDocument(doc);
        // 6.释放资源
        indexWriter.close();
    }

测试:

3.5 SmartChineseAnalyzer

特点 :对中文支持也不是很好,扩展性差,扩展词库,禁用词库和同义词库等不好处理。

这个需要引入中文分词器模块,pom文件添加

        <!-- Lucene提供的中文分词器模块,lucene-analyzers-smartcn:Lucene  的中文分词器 SmartChineseAnalyzer -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-smartcn</artifactId>
            <version>7.3.0</version>
        </dependency>

代码:

    @Test
    public void TestSmartChineseAnalyzer() throws Exception{
        // 1. 创建分词器,分析文档,对文档进行分词
        Analyzer analyzer = new SmartChineseAnalyzer();
        // 2. 创建Directory对象,声明索引库的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\dir"));
        // 3. 创建IndexWriteConfig对象,写入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter写入对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        // 5.写入到索引库,通过IndexWriter添加文档对象document
        Document doc = new Document();
        doc.add(new TextField("name", "vivo,X23。 8GB+128GB; 幻夜蓝",
                Field.Store.YES));
        indexWriter.addDocument(doc);
        // 6.释放资源
        indexWriter.close();
    }

测试:

4 第三方中文分词器

4.1 什么是中文分词器

学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开。所以对于英文,我们可以简单以空格判断某个字符串是否为一个单词,比如I love China,love 和 China很容易被程序区分开来。

而中文则以字为单位,字又组成词,字和词再组成句子。中文“我爱中国”就不一样了,电脑不知道“中国”是一个词语还是“爱中”是一个词语。

把中文的句子切分成有意义的词,就是中文分词,也称切词。我爱中国,分词的结果是:我、爱、中国。

4.2 第三方中文分词器简介

  • 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算法。

4.3 使用中文分词器IKAnalyzer

IKAnalyzer继承Lucene的Analyzer抽象类,使用IKAnalyzer和Lucene自带的分析器方法一样,将Analyzer测试代码改为IKAnalyzer测试中文分词效果。

如果使用中文分词器ik-analyzer,就需要在索引和搜索程序中使用一致的分词器:IK-analyzer。

1. 添加依赖, pom.xml中加入依赖

        <!-- IK中文分词器 -->
        <dependency>
            <groupId>com.github.magese</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>8.1.0</version>
        </dependency>

2. 加入配置文件:

非必要操作,如果想配置扩展词和停用词,就创建扩展词的文件和停用词的文件。

ext.dic:配置扩展词典。放专有名词,或者是我们认为需要强制将某些字分成一个词。凡是出现在扩展词典中的词,就会被强制分成一个词

stopword.dic:配置的停用词典,凡是出现在停用词典中的词,切分词的时候都会被过滤掉。

IKAnalyzer.cfg.xml:核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典 -->
    <entry key="ext_dict">ext.dic;</entry>

    <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords">stopword.dic;</entry>

</properties>

3. 测试代码

    @Test
    public void TestIKAnalyzer() throws Exception{
        // 1. 创建分词器,分析文档,对文档进行分词
        Analyzer analyzer = new IKAnalyzer();
        // 2. 创建Directory对象,声明索引库的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\dir"));
        // 3. 创建IndexWriteConfig对象,写入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter写入对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        // 5.写入到索引库,通过IndexWriter添加文档对象document
        Document doc = new Document();
        doc.add(new TextField("name", "vivo X23 8GB+128GB 幻夜蓝,水滴屏全面屏,游戏手机.移动联通电信全网通4G手机", Field.Store.YES));
        indexWriter.addDocument(doc);
        // 6.释放资源
        indexWriter.close();
    }

5. 测试结果如下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

netty学习第一课

技术主题 Netty是一个基于Java NIO&#xff08;非阻塞 I/O&#xff09;框架的网络编程框架。它提供了一系列的高级网络编程API&#xff0c;使得开发者可以非常容易地实现高性能、高可靠性的网络应用。Netty具有非常好的可扩展性和灵活性&#xff0c;能够很好地支持多种协议和数…

Fiddler抓包工具之fiddler的介绍及安装

Fiddler简介 Fiddler是比较好用的web代理调试工具之一&#xff0c;它能记录并检查所有客户端与服务端的HTTP/HTTPS请求&#xff0c;能够设置断点&#xff0c;篡改及伪造Request/Response的数据&#xff0c;修改hosts&#xff0c;限制网速&#xff0c;http请求性能统计&#xff…

从零实现一个数据库(DataBase) Go语言实现版 7.空闲列表: 重用页

英文源地址 由于我们的B树时不可变的, 每次对kv存储的更新都会在路径上创建新节点, 而不是更新当前节点, 从而使一些节点无法从最新版本访问到.我们需要从旧版本中重用这些不可访问的节点, 否则, 数据库文件将无限增长. 设计空闲列表 为了重用这些页, 我们将添加一个持久化存…

python处理字符串、文本实例及注释

1、多个界定符切割字符串 代码 line = asdf fjdk; afed, fjek,asdf, foo import re re.split(r[;,\s]\s*, line) 结果 在上面的例子中,分隔符可以是逗号,分号或者是空格,并且后面紧跟着任意个的空格。只要这个模式被找到,那么匹配的分隔符两边的实体都会被当成是结果中…

面了个20k的自动化测试,从腾讯出来的果然都有两把刷子···

现在找个会自动化测试的人真是难呀&#xff0c;10个里面有8个写了会自动化&#xff0c;但一问就是三不知 公司前段时间缺人&#xff0c;也面了不少测试&#xff0c;前面一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在15-20k&#xff0c;面试的…

技巧:如何查看github的热门趋势和star排行

目录 1. 查看github的热门趋势2. 查看github的star排行3. 如何查看项目star增长曲线 1. 查看github的热门趋势 手动找到入口&#xff0c;打开github&#xff0c;登录后&#xff0c;找到Explore并点击进入&#xff0c;找到Trending切换&#xff0c;列出的就是github当天所有语言…

目标检测常用模型之R-CNN、Fast R-CNN、Faster R-CNN

文章目录 一、模型分类1. 一阶段目标检测2. 二阶段目标检测 二、常见模型1. R-CNN2. Fast R-CNN3. Faster R-CNN 一、模型分类 2012年卷积神经网络(Convolutional Neural Networks, CNNs)的兴起将目标检测领域推向了新的台阶。基于CNNs的目标检测算法主要有两条技术发展路线&am…

国外顶尖高校、企业分享人工智能自学课程英文原课程分享

人工智能无疑已经是当下最火热的方向&#xff0c;在很多领域已经融入我们生活&#xff0c;ChatGPT,Midjourney只是其中一个细分热点。目前这个领域&#xff0c;虽说国内也有不少课程&#xff0c;但是大部分源头还得从英文资料中找。如何学到最新最强得人工智能技能&#xff0c;…

Mongodb——快速入门,2个小时足够了

目录 1、Mongodb概述 1.1、为何使用Mongodb&#xff1f; 1.2、业务应用场景 1.3、Mongodb和MySQL的区别 2、Mongodb安装 2.1、Windows系统中安装启动 3、Mongodb的操作 3.1、数据库操作 3.2、集合操作 3.2.1、集合显式创建 3.2.2、集合的隐式创建 3.2.3集合的删除 …

k8s进阶3——资源配额、资源限制

文章目录 一、基本了解1.1 资源计算1.2 调度机制1.3 服务质量等级 二、资源配额 ResourceQuota2.1 支持的限制资源2.2 配额作用域2.3 资源配额选型2.3.1 计算资源配额2.3.2 存储资源配额2.3.3 对象数量配额 三、资源限制 LimitRange3.1 限制资源大小值3.2 设置限制默认值3.3 限…

buu [NPUCTF2020]共 模 攻 击 1

题目描述: task: hint: 题目分析&#xff1a; 先看hint(提示)这一部分&#xff0c;标题已经提示了是共模攻击&#xff0c;看到有e1,e2,c1,c2,n也可以想到是共模攻击&#xff0c;之后得到c&#xff0c;继续往下做 此时有点不知如何下手&#xff0c;e 256 并且 gcd(e // 4,p…

接口测试工具Postman接口测试图文教程(超详细)

目录 一、前言 二、Postman安装和使用 三、请求方式 四、资金记录接口实例演示 一、前言 在前后端分离开发时&#xff0c;后端工作人员完成系统接口开发后&#xff0c;需要与前端人员对接&#xff0c;测试调试接口&#xff0c;验证接口的正确性可用性。而这要求前端开发进度…

games103——作业4

实验四主要使用 Shallow Wave 模拟流体 完整项目已上传至github。 文章目录 Height Feild(高度场)更新高度场更新速度场 Shallow Wave EquationDiscretization(离散化)一阶导数二阶导数 Discretized Shallow Wave EquationSolution 1Solution 2Pressure(压强)Viscosity(粘滞) 算…

​性能测试基础——性能测试方案

前面所说的测试分析等准备工作实际上最终目的是制定测试方案&#xff0c;测试方案一般包括&#xff1a; 项目的简要说明、项目系统结构、项目的业务结构、以及项目的性能需求、测试环境数据以及测试策略方法、测试案例、测试人员进度安排以及测试风险预估等等。 下面是一个一般…

FreeRTOS创建静态任务教程及所遇到的问题解决方法

静态任务和动态任务的区别 相对于动态任务&#xff0c;静态任务不需要动态分配内存&#xff0c;而是手动指定一个静态内存缓冲区&#xff0c;并在任务生命周期中一直使用该缓冲区。这可以避免动态内存分配时可能出现的内存碎片和内存泄漏问题&#xff0c;提高了系统的稳定性。…

【Python lxml、BeautifulSoup和html.parser区别介绍】零基础也能轻松掌握的学习路线与参考资料

区别介绍 &#xff08;1&#xff09;lxml lxml是Python的一个XML解析库&#xff0c;它基于libxml2和libxslt库构建&#xff0c;可以读取、操作和输出XML文档。lxml具有很强的性能和稳定性&#xff0c;在处理较大的XML文件时表现尤佳&#xff0c;并且支持XPath、CSS选择器等高…

PHP复习资料(未完待续)

&#xff08;未完待续&#xff0c;请持续关注此板块&#xff09; 【计科三四】雪课堂PHP期末模拟题&#xff1a;https://ks.wjx.top/vm/tUAmjxq.aspx# 【计科一二】PHP第一章练习题 https://ks.wjx.top/vm/QnjHad4.aspx# 【计科一二】PHP第二章练习题 https://ks.wjx.top/vm/h2…

ggplot绘制带误差棒、置信区间的柱状图,并调整颜色为渐变

ggplot绘制带误差棒、置信区间的柱状图,并调整颜色为渐变 简单绘制柱状图控制柱状宽度,间距调整颜色渐变简单绘制柱状图 要在ggplot中绘制带有置信区间的柱状图,你可以使用geom_bar和geom_errorbar函数来完成。下面是一个示例代码: library(ggplot2)# 创建一个示例数据集…

【LeetCode热题100】打卡第1天:两数之和

文章目录 两数之和⛅前言&#x1f512;题目&#x1f511;题解 两数之和 ⛅前言 大家好&#xff0c;我是知识汲取者&#xff0c;欢迎来到我们的LeetCode热题100刷题专栏&#xff01; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与…

《操作系统》期末最全复习题及解释答案

文章目录 选择题填空题简答题程序题综合题1.银行家算法2.页面置换算法3.进程调度算法4.磁盘调度算法5.求物理/逻辑地址6.分页存储管理7.可变分区分配算法 选择题 若信号量S的初值为2&#xff0c;且有3个进程共享此信号量&#xff0c;则S的取值范围是&#xff08;B &#xff09;…