Lucene IK分詞器集成,詞典擴展


 本文主要介紹在Lucene中集成IKAnalyzer

1 環境介紹

  系統:win10

  lucene版本:7.3.0   https://lucene.apache.org/

  jdk:1.8

 

2 IKAnalyzer 集成說明

      IK分詞器最先作為lucence上使用而開發,主要用於對中文的分詞,后來發展成獨立的分詞組件,目前只提供到lucence 4.0版本的支持,我們在使用4.0以后的版本的時候需要簡單的集成一下。

      IK需要集成一因為lucence4.0后,Analyer的createComponents方法的參數改變了。

      我們在ikAnalyzer包中提供的Lucence支持類中可以看到

      

      

    

        4.0后的版本中,該方法的參數只有一個fileldName,沒有第二個輸入流參數。故需要修改后使用

3 maven 依賴引用

<!-- lucene 核心模塊  -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>7.3.0</version>
</dependency>
<!-- ikanalyzer 中文分詞器  -->
<dependency>
<groupId>com.janeluo</groupId>
<artifactId>ikanalyzer</artifactId>
<version>2012_u6</version>

<exclusions>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
</exclusion>
</exclusions>
</dependency>

4 重寫IKAnalyer 類

   我們重命名為IKAnalyzer4Lucene7,我們把ik包下的ikanalyer類里面的內容全部復制到IKAnalyzer4Lucene7中即可。然后修改createComponents方法。

public class IKAnalyzer4Lucene7 extends Analyzer {

private boolean useSmart = false;

public IKAnalyzer4Lucene7() {
this(false);
}

public IKAnalyzer4Lucene7(boolean useSmart) {
super();
this.useSmart = useSmart;
}

public boolean isUseSmart() {
return useSmart;
}

public void setUseSmart(boolean useSmart) {
this.useSmart = useSmart;
}

@Override
protected TokenStreamComponents createComponents(String fieldName) {
IKTokenizer4Lucene7 tk = new IKTokenizer4Lucene7(this.useSmart);
return new TokenStreamComponents(tk);
}

}

  5 重寫IKTokenizer類

    我們重命名為IKTokenizer4Lucene7,我們把ik包下的iktokenizer類里面的內容全部復制到IKTokenizer4Lucene7中即可。然后修改構造方法。

public class IKTokenizer4Lucene7 extends Tokenizer {

// IK分詞器實現
private IKSegmenter _IKImplement;

// 詞元文本屬性
private final CharTermAttribute termAtt;
// 詞元位移屬性
private final OffsetAttribute offsetAtt;
// 詞元分類屬性(該屬性分類參考org.wltea.analyzer.core.Lexeme中的分類常量)
private final TypeAttribute typeAtt;
// 記錄最后一個詞元的結束位置
private int endPosition;

/**
* @param in
* @param useSmart
*/
public IKTokenizer4Lucene7(boolean useSmart) {
super();
offsetAtt = addAttribute(OffsetAttribute.class);
termAtt = addAttribute(CharTermAttribute.class);
typeAtt = addAttribute(TypeAttribute.class);
_IKImplement = new IKSegmenter(input, useSmart);
}

/*
* (non-Javadoc)
*
* @see org.apache.lucene.analysis.TokenStream#incrementToken()
*/
@Override
public boolean incrementToken() throws IOException {
// 清除所有的詞元屬性
clearAttributes();
Lexeme nextLexeme = _IKImplement.next();
if (nextLexeme != null) {
// 將Lexeme轉成Attributes
// 設置詞元文本
termAtt.append(nextLexeme.getLexemeText());
// 設置詞元長度
termAtt.setLength(nextLexeme.getLength());
// 設置詞元位移
offsetAtt.setOffset(nextLexeme.getBeginPosition(),
nextLexeme.getEndPosition());
// 記錄分詞的最后位置
endPosition = nextLexeme.getEndPosition();
// 記錄詞元分類
typeAtt.setType(nextLexeme.getLexemeTypeString());
// 返會true告知還有下個詞元
return true;
}
// 返會false告知詞元輸出完畢
return false;
}

/*
* (non-Javadoc)
*
* @see org.apache.lucene.analysis.Tokenizer#reset(java.io.Reader)
*/
@Override
public void reset() throws IOException {
super.reset();
_IKImplement.reset(input);
}

@Override
public final void end() {
// set final offset
int finalOffset = correctOffset(this.endPosition);
offsetAtt.setOffset(finalOffset, finalOffset);
}
}

  6 詞典擴展

    6.1 停用詞擴展

         1 在類目錄下創建IK的配置問題:IKAnalyzer.cfg.xml

         2  在配置文件中增加配置的停用詞文件的節點: <entry key="ext_stopwords">my_ext_stopword.dic</entry>

         3 在類目前下創建擴展停用詞文件my_ext_stopword.dic

         4, 在停用詞文件中添加,一行一個。

    6.2 擴展字典 

          字典中的詞,IK會作為一個整體去分詞,如‘厲害了我的國’,不會進行拆分

          1 在類目前下創建擴展詞文件ext.dic

          2 在文件中添加,一行一個。

          3 在配置文件中增加配置的停用詞文件的節點: <entry key="ext_dict">ext.dic</entry> 

    整體如下圖:

         

         配置文件IKAnalyer.cfg.xml:

         

        停用詞文件:

         

        擴展詞文件:

       

  

    7 IK分詞器使用效果

public class IkAnalyzerTestDemo {

private static void doToken(TokenStream ts) throws IOException {
ts.reset();
CharTermAttribute cta = ts.getAttribute(CharTermAttribute.class);
while (ts.incrementToken()) {
System.out.print(cta.toString() + "|");
}
System.out.println();
ts.end();
ts.close();
}

public static void main(String[] args) throws IOException {
String etext = "Analysis is one of the main causes of slow indexing. Simply put, ";
// String chineseText = "張三說的確實在理。";
String chineseText = "厲害了我的國一經播出,受到各方好評,強烈激發了國人的愛國之情、自豪感!";
// IKAnalyzer 細粒度切分
try (Analyzer ik = new IKAnalyzer4Lucene7();) {
TokenStream ts = ik.tokenStream("content", etext);
System.out.println("IKAnalyzer中文分詞器 細粒度切分,英文分詞效果:");
doToken(ts);
ts = ik.tokenStream("content", chineseText);
System.out.println("IKAnalyzer中文分詞器 細粒度切分,中文分詞效果:");
doToken(ts);
}

// IKAnalyzer 智能切分
try (Analyzer ik = new IKAnalyzer4Lucene7(true);) {
TokenStream ts = ik.tokenStream("content", etext);
System.out.println("IKAnalyzer中文分詞器 智能切分,英文分詞效果:");
doToken(ts);
ts = ik.tokenStream("content", chineseText);
System.out.println("IKAnalyzer中文分詞器 智能切分,中文分詞效果:");
doToken(ts);
}
}
}

  運行結果: 

  

      注意:一定要確認加載了擴展文件,否則不會生效。


免責聲明!

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



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