Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息
Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息
在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从TokenStream流中获取.
分词器的核心类Analyzer,TokenStream,Tokenizer,TokenFilter.
Analyzer
Lucene中的分词器有StandardAnalyzer,StopAnalyzer,SimpleAnalyzer,WhitespaceAnalyzer.
TokenStream
分词器做好处理之后得到的一个流,这个流中存储了分词的各种信息.可以通过TokenStream有效的获取到分词单元
Tokenizer
主要负责接收字符流Reader,将Reader进行分词操作.有如下一些实现类
KeywordTokenizer,
standardTokenizer,
CharTokenizer
|----WhitespaceTokenizer
|----LetterTokenizer
|----LowerCaseTokenizer
TokenFilter
将分好词的语汇单元进行各种各样的过滤.
查看分词器的分词信息

package com.icreate.analyzer.luence; import java.io.IOException;
import java.io.StringReader; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Version; /**
*
* AnalyzerUtil.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-4-14 上午11:05:45
*
* TODO :
*
*/
public class AnalyzerUtil { /**
*
* Description: 查看分词信息
* @param str 待分词的字符串
* @param analyzer 分词器
*
*/
public static void displayToken(String str,Analyzer analyzer){
try {
//将一个字符串创建成Token流
TokenStream stream = analyzer.tokenStream("", new StringReader(str));
//保存相应词汇
CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
while(stream.incrementToken()){
System.out.print("[" + cta + "]");
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
Analyzer aly1 = new StandardAnalyzer(Version.LUCENE_36);
Analyzer aly2 = new StopAnalyzer(Version.LUCENE_36);
Analyzer aly3 = new SimpleAnalyzer(Version.LUCENE_36);
Analyzer aly4 = new WhitespaceAnalyzer(Version.LUCENE_36); String str = "hello kim,I am dennisit,我是 中国人,my email is dennisit@163.com, and my QQ is 1325103287"; AnalyzerUtil.displayToken(str, aly1);
AnalyzerUtil.displayToken(str, aly2);
AnalyzerUtil.displayToken(str, aly3);
AnalyzerUtil.displayToken(str, aly4);
}
}

程序执行结果

[hello][kim][i][am][dennisit][我][是][中][国][人][my][email][dennisit][163][com][my][qq][1325103287]
[hello][kim][i][am][dennisit][我是][中国人][my][email][dennisit][com][my][qq]
[hello][kim][i][am][dennisit][我是][中国人][my][email][is][dennisit][com][and][my][qq][is]
[hello][kim,I][am][dennisit,我是][中国人,my][email][is][dennisit@163.com,][and][my][QQ][is][1325103287]

standardanalyzer将数字作为一个整体,每个单词都进行分隔
stopanalyzer将数字停用 中文不起作用,只坐空格分割
simpleanalyzer将数字停用 中文不起作用,只按照空格分割
whitespaceanalyzer按照空格分隔,中文不起作用
展示分词的详细信息

/**
*
* Description: 显示分词的全部信息
* @param str
* @param analyzer
*
*/
public static void displayAllTokenInfo(String str, Analyzer analyzer){
try {
//第一个参数只是标识性没有实际作用
TokenStream stream = analyzer.tokenStream("", new StringReader(str));
//获取词与词之间的位置增量
PositionIncrementAttribute postiona = stream.addAttribute(PositionIncrementAttribute.class);
//获取各个单词之间的偏移量
OffsetAttribute offseta = stream.addAttribute(OffsetAttribute.class);
//获取每个单词信息
CharTermAttribute chara = stream.addAttribute(CharTermAttribute.class);
//获取当前分词的类型
TypeAttribute typea = stream.addAttribute(TypeAttribute.class);
while(stream.incrementToken()){
System.out.print("位置增量" +postiona.getPositionIncrement()+":\t");
System.out.println(chara+"\t[" + offseta.startOffset()+" - " + offseta.endOffset() + "]\t<" + typea +">");
}
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
}

测试代码

Analyzer aly1 = new StandardAnalyzer(Version.LUCENE_36);
Analyzer aly2 = new StopAnalyzer(Version.LUCENE_36);
Analyzer aly3 = new SimpleAnalyzer(Version.LUCENE_36);
Analyzer aly4 = new WhitespaceAnalyzer(Version.LUCENE_36); String str = "hello kim,I am dennisit,我是 中国人,my email is dennisit@163.com, and my QQ is 1325103287"; AnalyzerUtil.displayAllTokenInfo(str, aly1);
AnalyzerUtil.displayAllTokenInfo(str, aly2);
AnalyzerUtil.displayAllTokenInfo(str, aly3);
AnalyzerUtil.displayAllTokenInfo(str, aly4);

程序运行结果

位置增量1: hello [0 - 5] <type=<ALPHANUM>>
位置增量1: kim [6 - 9] <type=<ALPHANUM>>
位置增量1: i [10 - 11] <type=<ALPHANUM>>
位置增量1: am [12 - 14] <type=<ALPHANUM>>
位置增量1: dennisit [15 - 23] <type=<ALPHANUM>>
位置增量1: 我 [24 - 25] <type=<IDEOGRAPHIC>>
位置增量1: 是 [25 - 26] <type=<IDEOGRAPHIC>>
位置增量1: 中 [27 - 28] <type=<IDEOGRAPHIC>>
位置增量1: 国 [28 - 29] <type=<IDEOGRAPHIC>>
位置增量1: 人 [29 - 30] <type=<IDEOGRAPHIC>>
位置增量1: my [31 - 33] <type=<ALPHANUM>>
位置增量1: email [34 - 39] <type=<ALPHANUM>>
位置增量2: dennisit [43 - 51] <type=<ALPHANUM>>
位置增量1: 163 [52 - 55] <type=<NUM>>
位置增量1: com [56 - 59] <type=<ALPHANUM>>
位置增量2: my [65 - 67] <type=<ALPHANUM>>
位置增量1: qq [68 - 70] <type=<ALPHANUM>>
位置增量2: 1325103287 [74 - 84] <type=<NUM>>
位置增量1: hello [0 - 5] <type=word>
位置增量1: kim [6 - 9] <type=word>
位置增量1: i [10 - 11] <type=word>
位置增量1: am [12 - 14] <type=word>
位置增量1: dennisit [15 - 23] <type=word>
位置增量1: 我是 [24 - 26] <type=word>
位置增量1: 中国人 [27 - 30] <type=word>
位置增量1: my [31 - 33] <type=word>
位置增量1: email [34 - 39] <type=word>
位置增量2: dennisit [43 - 51] <type=word>
位置增量1: com [56 - 59] <type=word>
位置增量2: my [65 - 67] <type=word>
位置增量1: qq [68 - 70] <type=word>
位置增量1: hello [0 - 5] <type=word>
位置增量1: kim [6 - 9] <type=word>
位置增量1: i [10 - 11] <type=word>
位置增量1: am [12 - 14] <type=word>
位置增量1: dennisit [15 - 23] <type=word>
位置增量1: 我是 [24 - 26] <type=word>
位置增量1: 中国人 [27 - 30] <type=word>
位置增量1: my [31 - 33] <type=word>
位置增量1: email [34 - 39] <type=word>
位置增量1: is [40 - 42] <type=word>
位置增量1: dennisit [43 - 51] <type=word>
位置增量1: com [56 - 59] <type=word>
位置增量1: and [61 - 64] <type=word>
位置增量1: my [65 - 67] <type=word>
位置增量1: qq [68 - 70] <type=word>
位置增量1: is [71 - 73] <type=word>
位置增量1: hello [0 - 5] <type=word>
位置增量1: kim,I [6 - 11] <type=word>
位置增量1: am [12 - 14] <type=word>
位置增量1: dennisit,我是 [15 - 26] <type=word>
位置增量1: 中国人,my [27 - 33] <type=word>
位置增量1: email [34 - 39] <type=word>
位置增量1: is [40 - 42] <type=word>
位置增量1: dennisit@163.com, [43 - 60] <type=word>
位置增量1: and [61 - 64] <type=word>
位置增量1: my [65 - 67] <type=word>
位置增量1: QQ [68 - 70] <type=word>
位置增量1: is [71 - 73] <type=word>
位置增量1: 1325103287 [74 - 84] <type=word>

自定义stop分词器
继承Analyzer复写public TokenStream tokenStream(String filename,Reader reader)方法

package org.dennisit.lucene.util;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Set; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.LetterTokenizer;
import org.apache.lucene.analysis.LowerCaseFilter;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.StopFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Version; /**
*
* org.dennisit.lucene.utilMyStopAnalyzer.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-4-14 下午12:06:08
*
* TODO :
*
*/
public class MyStopAnalyzer extends Analyzer{ private Set stops; /**
* 在原来停用词基础上增加自己的停用词
* @param stopwords 自定义停用词采用数组传递
*/
public MyStopAnalyzer(String[] stopwords){
//会自动将字符串数组转换为Set
stops = StopFilter.makeStopSet(Version.LUCENE_36,stopwords,true);
//将原有的停用词加入到现在的停用词
stops.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
} /**
* 不传入参数表示使用原来默认的停用词
*/
public MyStopAnalyzer(){
//获取原有的停用词
stops = StopAnalyzer.ENGLISH_STOP_WORDS_SET;
} @Override
public TokenStream tokenStream(String filename,Reader reader){
//为自定义分词器设定过滤链和Tokenizer
return new StopFilter(Version.LUCENE_36,
new LowerCaseFilter(Version.LUCENE_36,
new LetterTokenizer(Version.LUCENE_36,reader)),
stops);
} /**
*
* Description: 查看分词信息
* @param str 待分词的字符串
* @param analyzer 分词器
*
*/
public static void displayToken(String str,Analyzer analyzer){
try {
//将一个字符串创建成Token流
TokenStream stream = analyzer.tokenStream("", new StringReader(str));
//保存相应词汇
CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
while(stream.incrementToken()){
System.out.print("[" + cta + "]");
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
//获取原来的停用词
Analyzer myAnalyzer1 = new MyStopAnalyzer();
//追加自己的停用词
Analyzer myAnalyzer2 = new MyStopAnalyzer(new String[]{"hate","fuck"});
//分词处理的句子
String text = "fuck! I hate you very much"; displayToken(text, myAnalyzer1);
displayToken(text, myAnalyzer2);
}
}

程序运行结果

[fuck][i][hate][you][very][much]
[i][you][very][much]

在此感谢孔浩老师,关于Lucene的深入,孔老师的教程讲的不错![Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息]
Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息的更多相关文章
- 【Lucene3.6.2入门系列】第05节_自定义停用词分词器和同义词分词器
首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import j ...
- 自然语言处理之中文分词器-jieba分词器详解及python实战
(转https://blog.csdn.net/gzmfxy/article/details/78994396) 中文分词是中文文本处理的一个基础步骤,也是中文人机自然语言交互的基础模块,在进行中文自 ...
- python装饰器内获取函数有用信息方法
装饰器内获取函数有用信息方法 .__doc__用于得到函数注释信息 .__name_用于得到函数名 在函数引用装饰器的时候,函数名会变为装饰器内部执行该函数的名字,所有在直接执行函数名加.__doc_ ...
- Elasticsearch(10) --- 内置分词器、中文分词器
Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...
- Elasticsearch修改分词器以及自定义分词器
Elasticsearch修改分词器以及自定义分词器 参考博客:https://blog.csdn.net/shuimofengyang/article/details/88973597
- 钉钉开发入门,微应用识别用户身份,获取用户免登授权码code,获取用户userid,获取用户详细信息
最近有个需求,在钉钉内,点击微应用,获取用户身份,根据获取到的用户身份去企业内部的用户中心做校验,校验通过,相关子系统直接登陆; 就是在获取这个用户身份的时候,网上的资料七零八落的,找的人烦躁的很,所 ...
- 微信小程序 报错 “对应的服务器无效。控制台输入 showRequestInfo()可以获取更详细信息”
之前做的项目突然无法读出数据了,一测试发现报这个错误==>对应的服务器无效.控制台输入 showRequestInfo()可以获取更详细信息,后来发现是SSL证书到期了.重新申请了一个证书,免费 ...
- NX二次开发-UFUN获取工程图详细信息UF_DRAW_ask_drawing_info
NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_part.h> UF_initialize ...
- 利用IK分词器,自定义分词规则
IK分词源码下载地址:https://code.google.com/p/ik-analyzer/downloads/list lucene源码下载地址:http://www.eu.apache.or ...
随机推荐
- iOS8自适应布局视频教程
联系:http://www.elsyy.com/course/6480 这是颐和园最近录制iOS8视频课程.简介iOS8出现在自适应布局. 本教程的书,颐和园<ios8 swift编程指南> ...
- ajax——client访问webservice基本用法
学前aps.net当我学会了使用服务器端的访问webservice方法,然后实现一个样本:web server模拟网上购物,今天学习asp.net ajax的时候学习到了client直接訪问webse ...
- EasyUI combox实现联动
多的时间将被用于combox联动效应.一个选择combox的值自己主动出这值有关相应的其他信息,例如省市联动.最近,我刚刚会见了班似要求,随着EasyUI combobox 控制完成.假设ASP.N ...
- 基于 自己定义注解 和 aop 实现使用memcache 对数据库的缓存 演示样例
好久没更新blog了,在新公司打拼了两个月,每天都从早忙到晚,学到了非常多东西,可是没有时间来更新blog了.... 以下開始解说这次的主题 公司老大让我研究 ocs 就是阿里云的 开放缓存服务 点击 ...
- Jquery页面中添加键盘按键事件,如ESC事件
$(document).keydown(function(event){ if(event.keyCode == 38 || event.keyCode == 104){ i--; if(i<= ...
- Magicodes.NET框架
Magicodes.NET框架之路——让代码再飞一会(ASP.NET Scaffolding) 首先感谢大家对Magicodes.NET框架的支持.就如我上篇所说,框架成熟可能至少还需要一年,毕竟 ...
- AppiumDriver升级到2.0.0版本引发的问题--Cannot instantiate the type AppiumDriver
1. 问题描述和起因 在使用Appium1.7.0及其以下版本的时候,我们可以直接使用如下代码来创建一个AppiumDriver实例进行对安卓设备的操作. driver = new AndroidDr ...
- Wowza流媒体Live直播和VOD点播配置实战
Wowza是当今可以说最流行的流媒体服务器之一,近来因为需要搭建相应的服务器,但又不想用camera等作真实的直播,所以想办法用媒体文件转换成直播流再提供给Wowza进行直播.这里把该设置步骤以及设计 ...
- android微信付费
原文地址:http://blog.csdn.net/intbird 微信官方文档地址:t=resource/res_main_tmpl&verify=1&lang=zh_CN" ...
- 使用javaservice 将jboss 注册为服务
近来做项目,需要jboss定期重新启动.不想再看到jboss启动那个黑洞洞的窗口,就想着把它注册为服务,然后在net start.恰好objectweb上有个open source的javaservi ...