本文共 7862 字,大约阅读时间需要 26 分钟。
分析器,分词器组件的核心API,它的职责:构建真正对文本进行分词处理的TokenStream(分词处理器)。通过调用它的如下两个方法,得到输入文本的分词处理器。
public final TokenStream tokenStream(String fieldName, Reader reader)
public final TokenStream tokenStream(String fieldName, String text)
Analizer中唯一的抽象方法,扩展点。通过提供该方法的实现来实现自己的Analyzer。
返回值为 TokenStreamComponents 分词处理器组件。
参数说明:fieldName,如果我们需要为不同的字段创建不同的分词处理器组件,则可根据这个参数来判断。否则,就用不到这个参数。
分词处理器组件:这个类中封装有供外部使用的TokenStream分词处理器。提供了对source(源)和sink(供外部使用分词处理器)两个属性的访问方法。
分词器处理项,负责对输入文本完成分词、处理。
TokenStream 的两类子类
Tokenizer:分词器,输入是Reader字符流的TokenStream,完成从流中分出分项
TokenFilter:分项过滤器,它的输入是另一个TokenStream,完成对从上一个TokenStream中流出的token的特殊处理。 TokenStream 继承了 AttributeSourceAttribute 属性 ,TokenAttribute 分项属性(分项信息),如 分项的词、词的索引位置等等。这些属性通过不同的Tokenizer /TokenFilter处理统计得出。不同的Tokenizer/TokenFilter组合,就会有不同的分项信息。
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 。
1、从tokenStream获得你想要获得分项属性对象(信息是存放在属性对象中的) 2、调用 tokenStream 的 reset() 方法,进行重置。因为tokenStream是重复利用的。 3、循环调用tokenStream的incrementToken(),一个一个分词,直到它返回false 4、在循环中取出每个分项你想要的属性值。 5、调用tokenStream的end(),执行任务需要的结束处理。 6、调用tokenStream的close()方法,释放占有的资源。
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>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/