博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucene-分词器(2)
阅读量:4037 次
发布时间:2019-05-24

本文共 7862 字,大约阅读时间需要 26 分钟。

Lucene-分词器API

 1.  org.apache.lucene.analysi.Analyzer

    分析器,分词器组件的核心API,它的职责:构建真正对文本进行分词处理的TokenStream(分词处理器)。通过调用它的如下两个方法,得到输入文本的分词处理器

    public final TokenStream tokenStream(String fieldName, Reader reader)

    public final TokenStream tokenStream(String fieldName, String text)

 2.TokenStreamComponents  createComponents(String fieldName)

          Analizer中唯一的抽象方法,扩展点。通过提供该方法的实现来实现自己的Analyzer。

          返回值为 TokenStreamComponents  分词处理器组件。

       参数说明:fieldName,如果我们需要为不同的字段创建不同的分词处理器组件,则可根据这个参数来判断。否则,就用不到这个参数。

3.TokenStreamComponents

     分词处理器组件:这个类中封装有供外部使用的TokenStream分词处理器。提供了对source()sink(供外部使用分词处理器)两个属性的访问方法。

4.org.apache.lucene.analysis.TokenStream

     分词器处理项,负责对输入文本完成分词、处理。

    TokenStream 的两类子类

    Tokenizer:分词器,输入是Reader字符流的TokenStream,完成从流中分出分项

    TokenFilter:分项过滤器,它的输入是另一个TokenStream,完成对从上一个TokenStream中流出的token的特殊处理。
    TokenStream 继承了 AttributeSource

    Attribute 属性 ,TokenAttribute  分项属性(分项信息),如 分项的词、词的索引位置等等。这些属性通过不同的Tokenizer        /TokenFilter处理统计得出。不同的Tokenizer/TokenFilter组合,就会有不同的分项信息。

5.AttributeSource使用规则说明

1、某个TokenStream实现中如要存储分项属性,通过AttributeSource的两个add方法之一,往AttributeSource中加入属性对象。

<T extends Attribute> T addAttribute(Class<T> attClass)
该方法要求传人你需要添加的属性的接口类(继承Attribute),返回对应的实现类实例给你。从接口到实例,这就是为什么需要AttributeFactory的原因。
void addAttributeImpl(AttributeImpl att)
2、加入的每一个Attribute实现类在AttributeSource中只会有一个实例,分词过程中,分项是重复使用这一实例来存放分项的属性信息。重复调用add方法添加它返回已存储的实例对象。
3、要获取分项的某属性信息,则需持有某属性的实例对象,通过addAttribute方法或getAttribure方法获得Attribute对象,再调用实例的方法来获取、设置值
4、在TokenStream中,我们用自己实现的Attribute,默认的工厂。当我们调用这个add方法时,它怎么知道实现类是哪个?这里有一定规则要遵守:
     1)、自定义的属性接口 MyAttribute  继承 Attribute
     2)、自定义的属性实现类必须继承 Attribute,实现自定义的接口MyAttribute
     3)、自定义的属性实现类必须提供无参构造方法
     4)、为了让默认工厂能根据自定义接口找到实现类,实现类名需为 接口名+Impl 。

6.TokenStream 的使用步骤。

1、从tokenStream获得你想要获得分项属性对象(信息是存放在属性对象中的)

2、调用 tokenStream 的 reset() 方法,进行重置。因为tokenStream是重复利用的。
3、循环调用tokenStream的incrementToken(),一个一个分词,直到它返回false
4、在循环中取出每个分项你想要的属性值。
5、调用tokenStream的end(),执行任务需要的结束处理。
6、调用tokenStream的close()方法,释放占有的资源。

7.Lucene提供的分词器

1)<!-- Lucene提供的中文分词器模块,lucene-analyzers-smartcn -->

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers-smartcn</artifactId>
    <version>7.3.0</version>
</dependency>

2)IKAnalyzer

开源、轻量级的中文分词器,应用比较多,最先是作为lucene上使用而开发,后来发展为独立的分词组件。

只提供到Lucene 4.0版本的支持。我们在4.0以后版本Lucene中使用就需要简单集成一下。

<!-- ikanalyzer 中文分词器  -->
<dependency>
    <groupId>com.janeluo</groupId>
    <artifactId>ikanalyzer</artifactId>
    <version>2012_u6</version>
    <exclusions>
    <exclusion>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    </exclusion>
    <exclusion>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    </exclusion>
    <exclusion>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers-common</artifactId>
    </exclusion>
    </exclusions>
</dependency>

<!--  lucene-queryparser 查询分析器模块 -->

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    <version>7.3.0</version>
</dependency>

8.扩展 IKAnalyzer的停用词

Ik中默认的停用词很少,可扩展它。可从网址:,下载一份比较全的停用词。

Ik中停用词的扩展步骤:
1、在类目录下创建IK的配置文件:IKAnalyzer.cfg.xml
2、在配置文件中增加配置扩展停用词文件的节点:
 <entry key=“ext_stopwords”>my_ext_stopword.dic</entry>  
   如有多个,以“;”间隔
3、在类目录下创建我们的扩展停用词文件 my_ext_stopword.dic
4、编辑该文件加入停用词,一行一个
注:文件编码一定是UTF-8

    

IK Analyzer 扩展配置
ext.dic
my_ext_stopword.dic

自定义分分词器实现

package com.dongsheng.lucene.dslucene.lucene;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.TokenFilter;import org.apache.lucene.analysis.TokenStream;import org.apache.lucene.analysis.Tokenizer;import org.apache.lucene.util.Attribute;import org.apache.lucene.util.AttributeImpl;import org.apache.lucene.util.AttributeReflector;import java.io.IOException;/*** *@author dongsheng *@date 2020/2/19 16:47 *@version 1.0.0 *@Description */public class MyWhitespaceAnalyzer extends Analyzer {    @Override    protected TokenStreamComponents createComponents(String fieldName) {        Tokenizer source = new MyWhitespaceTokenizer();        TokenStream filter = new MyLowerCaseTokenFilter(source);        return new TokenStreamComponents(source, filter);    }        //自定义分词器读取    static class MyWhitespaceTokenizer extends Tokenizer {        // 需要记录的属性        // 词        MyCharAttribute charAttr = this.addAttribute(MyCharAttribute.class);        char[] buffer = new char[255];        int length = 0;        int c;        @Override        public boolean incrementToken() throws IOException {            // 清除所有的词元属性            clearAttributes();            length = 0;            while (true) {                c = this.input.read();                if (c == -1) {                    if (length > 0) {                        // 复制到charAttr                        this.charAttr.setChars(buffer, length);                        return true;                    } else {                        return false;                    }                }                if (Character.isWhitespace(c)) {                    if (length > 0) {                        // 复制到charAttr                        this.charAttr.setChars(buffer, length);                        return true;                    }                }                buffer[length++] = (char) c;            }        }    }    //自定义分词项    public static class MyLowerCaseTokenFilter extends TokenFilter {        public MyLowerCaseTokenFilter(TokenStream input) {            super(input);        }        MyCharAttribute charAttr = this.addAttribute(MyCharAttribute.class);        @Override        public boolean incrementToken() throws IOException {            boolean res = this.input.incrementToken();            if (res) {                char[] chars = charAttr.getChars();                int length = charAttr.getLength();                if (length > 0) {                    for (int i = 0; i < length; i++) {                        chars[i] = Character.toLowerCase(chars[i]);                    }                }            }            return res;        }    }    public static interface MyCharAttribute extends Attribute {        void setChars(char[] buffer, int length);        char[] getChars();        int getLength();        String getString();    }    public static class MyCharAttributeImpl extends AttributeImpl            implements MyCharAttribute {        private char[] chatTerm = new char[255];        private int length = 0;        @Override        public void setChars(char[] buffer, int length) {            this.length = length;            if (length > 0) {                System.arraycopy(buffer, 0, this.chatTerm, 0, length);            }        }        public char[] getChars() {            return this.chatTerm;        }        public int getLength() {            return this.length;        }        @Override        public String getString() {            if (this.length > 0) {                return new String(this.chatTerm, 0, length);            }            return null;        }        @Override        public void clear() {            this.length = 0;        }        @Override        public void reflectWith(AttributeReflector reflector) {        }        @Override        public void copyTo(AttributeImpl target) {        }    }    public static void main(String[] args) {      //中间空格的代替|        String text = "An AttributeSource contains a list of different AttributeImpls, and methods to add and get them. ";        try (Analyzer ana = new MyWhitespaceAnalyzer();             TokenStream ts = ana.tokenStream("test", text);) {            MyCharAttribute ca = ts.getAttribute(MyCharAttribute.class);            ts.reset();            while (ts.incrementToken()) {                System.out.print(ca.getString() + "|");            }            ts.end();            System.out.println();        } catch (IOException e) {            e.printStackTrace();        }    }}

结果输出:

an|attributesource|contains|a|list|of|different|attributeimpls,|and|methods|to|add|and|get|them.| 

 

 

转载地址:http://xujdi.baihongyu.com/

你可能感兴趣的文章
springboot+springsecurity+jwt进行系统权限开发
查看>>
使用轻量级工具emoji-java处理emoji表情字符
查看>>
排序算法的C语言实现C代码
查看>>
c语言快排函数调用方法模板
查看>>
c语言实现多行输入输出数据
查看>>
查找算法
查看>>
C语言单链表实现
查看>>
SQL基本命令集合整理
查看>>
QT中json的生成和解析
查看>>
std::function 和 std::bind 的简单例子
查看>>
CFormView简介
查看>>
Visual Studio 2010 与 VC++ 6.0 的操作差异(一)之对话框中添加OnInitDialog()函数
查看>>
VC的MFC里面控件的ID使用ID_XXXXX和IDR_XXXXX的区别
查看>>
VC++ 获取ListControl选中行
查看>>
用VC++实现应用程序窗口的任意分割(2)
查看>>
“class”类型重定义,include(头文件)重复加载 QT /c++
查看>>
MFC框架类、文档类、视图类相互访问的方法
查看>>
<转>文档视图指针互获
查看>>
C++中头文件相互包含的几点问题
查看>>
内存设备描述表
查看>>