在此回復牛妞的關於程序中分詞器的問題,其實可以直接很簡單的在詞庫中配置就好了,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獲取分詞詳細信息]