博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息
阅读量:4603 次
发布时间:2019-06-09

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

在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,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  : 苏若年    发送邮件 *     *  @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]    
>位置增量1: kim [6 - 9]
>位置增量1: i [10 - 11]
>位置增量1: am [12 - 14]
>位置增量1: dennisit [15 - 23]
>位置增量1: 我 [24 - 25]
>位置增量1: 是 [25 - 26]
>位置增量1: 中 [27 - 28]
>位置增量1: 国 [28 - 29]
>位置增量1: 人 [29 - 30]
>位置增量1: my [31 - 33]
>位置增量1: email [34 - 39]
>位置增量2: dennisit [43 - 51]
>位置增量1: 163 [52 - 55]
>位置增量1: com [56 - 59]
>位置增量2: my [65 - 67]
>位置增量1: qq [68 - 70]
>位置增量2: 1325103287 [74 - 84]
>位置增量1: hello [0 - 5]
位置增量1: kim [6 - 9]
位置增量1: i [10 - 11]
位置增量1: am [12 - 14]
位置增量1: dennisit [15 - 23]
位置增量1: 我是 [24 - 26]
位置增量1: 中国人 [27 - 30]
位置增量1: my [31 - 33]
位置增量1: email [34 - 39]
位置增量2: dennisit [43 - 51]
位置增量1: com [56 - 59]
位置增量2: my [65 - 67]
位置增量1: qq [68 - 70]
位置增量1: hello [0 - 5]
位置增量1: kim [6 - 9]
位置增量1: i [10 - 11]
位置增量1: am [12 - 14]
位置增量1: dennisit [15 - 23]
位置增量1: 我是 [24 - 26]
位置增量1: 中国人 [27 - 30]
位置增量1: my [31 - 33]
位置增量1: email [34 - 39]
位置增量1: is [40 - 42]
位置增量1: dennisit [43 - 51]
位置增量1: com [56 - 59]
位置增量1: and [61 - 64]
位置增量1: my [65 - 67]
位置增量1: qq [68 - 70]
位置增量1: is [71 - 73]
位置增量1: hello [0 - 5]
位置增量1: kim,I [6 - 11]
位置增量1: am [12 - 14]
位置增量1: dennisit,我是 [15 - 26]
位置增量1: 中国人,my [27 - 33]
位置增量1: email [34 - 39]
位置增量1: is [40 - 42]
位置增量1: dennisit@163.com, [43 - 60]
位置增量1: and [61 - 64]
位置增量1: my [65 - 67]
位置增量1: QQ [68 - 70]
位置增量1: is [71 - 73]
位置增量1: 1325103287 [74 - 84]
View Code

 

自定义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  : 苏若年         发送邮件 *     *  @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获取分词详细信息]

 

转载于:https://www.cnblogs.com/dennisit/p/3258664.html

你可能感兴趣的文章
CF219D Choosing Capital for Treeland
查看>>
luogu P3809 【模板】后缀排序
查看>>
JVM 调优工具
查看>>
SCTF 2014 pwn题目分析
查看>>
集合以及特殊集合
查看>>
USACO 2.2 Runaround Numbers
查看>>
Matlab画图-非常具体,非常全面
查看>>
365. Water and Jug Problem
查看>>
SQL数据库数据检索top和distinct
查看>>
平衡搜索树--红黑树 RBTree
查看>>
sqlite驱动下载
查看>>
让IE6/IE7/IE8浏览器支持CSS3属性
查看>>
队列实现霍夫曼树
查看>>
【Java】图片高质量缩放类
查看>>
Python :类中设置默认属性并修改
查看>>
磁盘管理综合测试
查看>>
Unity3d Shader开发(三)Pass(Pass Tags,Name,BindChannels )
查看>>
UMLet
查看>>
从父控件移除控件
查看>>
calc()制作自适应布局
查看>>