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:[email protected]">发送邮件</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 [email protected], 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 [email protected], and my QQ is 1325103287";

        

        AnalyzerUtil.displayAllTokenInfo(str, aly1);

        AnalyzerUtil.displayAllTokenInfo(str, aly2);

        AnalyzerUtil.displayAllTokenInfo(str, aly3);

        AnalyzerUtil.displayAllTokenInfo(str, aly4);

程序运行结果

Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息
位置增量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>
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  : 苏若年         <a href="mailto:[email protected]">发送邮件</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)