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>
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: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獲取分詞詳細信息]

在線交談

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM