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获取分词详细信息]

热爱生活,热爱Coding,敢于挑战,用于探索 ...
 
分类: JavaEE数据挖掘
标签: lucene

Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息的更多相关文章

  1. 【Lucene3.6.2入门系列】第05节_自定义停用词分词器和同义词分词器

    首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import j ...

  2. 自然语言处理之中文分词器-jieba分词器详解及python实战

    (转https://blog.csdn.net/gzmfxy/article/details/78994396) 中文分词是中文文本处理的一个基础步骤,也是中文人机自然语言交互的基础模块,在进行中文自 ...

  3. python装饰器内获取函数有用信息方法

    装饰器内获取函数有用信息方法 .__doc__用于得到函数注释信息 .__name_用于得到函数名 在函数引用装饰器的时候,函数名会变为装饰器内部执行该函数的名字,所有在直接执行函数名加.__doc_ ...

  4. Elasticsearch(10) --- 内置分词器、中文分词器

    Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...

  5. Elasticsearch修改分词器以及自定义分词器

    Elasticsearch修改分词器以及自定义分词器 参考博客:https://blog.csdn.net/shuimofengyang/article/details/88973597

  6. 钉钉开发入门,微应用识别用户身份,获取用户免登授权码code,获取用户userid,获取用户详细信息

    最近有个需求,在钉钉内,点击微应用,获取用户身份,根据获取到的用户身份去企业内部的用户中心做校验,校验通过,相关子系统直接登陆; 就是在获取这个用户身份的时候,网上的资料七零八落的,找的人烦躁的很,所 ...

  7. 微信小程序 报错 “对应的服务器无效。控制台输入 showRequestInfo()可以获取更详细信息”

    之前做的项目突然无法读出数据了,一测试发现报这个错误==>对应的服务器无效.控制台输入 showRequestInfo()可以获取更详细信息,后来发现是SSL证书到期了.重新申请了一个证书,免费 ...

  8. NX二次开发-UFUN获取工程图详细信息UF_DRAW_ask_drawing_info

    NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_part.h> UF_initialize ...

  9. 利用IK分词器,自定义分词规则

    IK分词源码下载地址:https://code.google.com/p/ik-analyzer/downloads/list lucene源码下载地址:http://www.eu.apache.or ...

随机推荐

  1. php exit、return、break、continue之间的差别,具体介绍

    相信大家在php开发中有几个经常使用的停止程序和循环的keyword的误区( exit.return.break.continue) exit 退出全部脚本,是个函数 return 语言结构的使用方法 ...

  2. 再谈IE的浏览器模式和文档模式

    原文:再谈IE的浏览器模式和文档模式 以前在 “IE8兼容视图(IE7 mode)与独立IE7的区别”一文中曾经涉及过浏览器模式和文档模式,但二者的区别却不甚了了,现在有了新的认识,再补充一下. 1. ...

  3. (工具)source insight高速增加时间代码

    这篇文章是程序代码更改由其他用户. 不是原厂原装,例如下列总结,使用作为个人笔记. (1)打开projectbase.打开文件Utils.em,插入下面代码: //插入时间 macro MonthTo ...

  4. 异常处理 Access to the path is denied

    在需要进行读写操作的目录下添加Network Service这个帐号, 由于在iis 6.0中,默认的应用程序池中的标示用的是Network Service, 所以在进程中是使用Network Ser ...

  5. IIS 7.5 使用URL Rewrite模块简单设置网页跳转

    原文 IIS 7.5 使用URL Rewrite模块简单设置网页跳转 我们都知道Apache可以在配置文件里方便的设置针对网页或网站的rewrite,但是最近接手了一组IIS服务器,发现这货简单的没有 ...

  6. [Unity3D]Unity3D游戏开发Android内嵌视图Unity查看

    ---------------------------------------------------------------------------------------------------- ...

  7. PAT 1006. Sign In and Sign Out

    #include<iostream> #include<string> using namespace std; int main(){ int cnt;cin>> ...

  8. PHP 17: MySQL的简单介绍

    原文:PHP 17: MySQL的简单介绍 这一章将简单介绍MySQL的基本知识. 本文来自http://lib.hackbase.com/html/8/35125.htm. MySQL是最受欢迎的开 ...

  9. DDD,ORM还是Ado.Net

    三层还是DDD,ORM还是Ado.Net,何去何从? 我本想把这个问题放到博问去,前几次有去博问问过之类的问题,无奈大神们可能都不屑回答别人的低级问题.所以放到随笔里,一方面把自己对ORM.架构的一些 ...

  10. Linux文件系统文件大小限制

    去阿里面试,被问到了Linux文件系统中文件大小的限制,当时就无语了.学操作系统时这些都是现算的,回来赶紧查一下. 以下为红帽ext3文件系统所支持的max file size和max filesys ...