Lucene關鍵字高亮顯示

在Lucene的org.apache.lucene.search.highlight包中提供了關於高亮顯示檢索關鍵字的工具。使用百度、Google搜索的時候,檢索結果顯示的時候,在摘要中實現與關鍵字相同的詞條進行高亮顯示,百度和Google指定紅色高亮顯示。
有了Lucene提供的高亮顯示的工具,可以很方便地實現高亮顯示的功能。
高亮顯示,就是根據用戶輸入的檢索關鍵字,檢索找到該關鍵字對應的檢索結果文件,提取對應於該文件的摘要文本,然後根據設置的高亮格式,將格式寫入到摘要文本中對應的與關鍵字相同或相似的詞條上,在網頁上顯示出來,該摘要中的與關鍵字有關的文本就會以高亮的格式顯示出來。
Lucene中org.apache.lucene.search.highlight.SimpleHTMLFormatter類可以構造一個高亮格式,這是最簡單的構造方式,例如:
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
構造方法聲明爲public SimpleHTMLFormatter(String preTag, String postTag),因爲這種高亮格式是依賴於網頁文件的,HTML文件中是以標記(tag)來標識的,即存在一個preTag和一個postTag。
上面構造的高亮格式是摘要中出現的關鍵字使用紅色來顯示,區分其它文本。
通過構造好的高亮格式對象,來構造一個org.apache.lucene.search.highlight.Highlighter實例,然後根據對檢索結果得到的Field的文本內容(這裏是指摘要文本)進行切分,找到與檢索關鍵字相同或相似的詞條,將高亮格式加入到摘要文本中,返回一個新的、帶有格式的摘要文本,在網頁上就可以呈現高亮顯示。
下面實現一個簡單的例子,展示實現高亮顯示的處理過程。
測試類如下所示:
package org.shirdrn.lucene.learn.highlight;
import java.io.IOException;
import java.io.StringReader;
import net.teamhot.lucene.ThesaurusAnalyzer;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
public class MyHighLighter {

private String indexPath = "F:\\index";
private Analyzer analyzer;
private IndexSearcher searcher;

public MyHighLighter(){
   analyzer = new ThesaurusAnalyzer();
}

public void createIndex() throws IOException {   // 該方法建立索引
   IndexWriter writer = new IndexWriter(indexPath,analyzer,true);
   Document docA = new Document();
   String fileTextA = "因爲火燒雲總是燃燒着消失在太陽衝下地平線的時刻,然後便是寧靜的自然的天籟,沒有誰會在這樣的時光的鏡片裏傷感自語,因爲燦爛給人以安靜的舒適感。";
   Field fieldA = new Field("contents", fileTextA, Field.Store.YES,Field.Index.TOKENIZED);
   docA.add(fieldA);
  
   Document docB = new Document();
   String fileTextB = "因爲帶有以傷痕爲代價的美麗風景總是讓人不由地惴惴不安,緊接着襲面而來的抑或是病痛抑或是災難,沒有誰會能夠安逸着恬然,因爲模糊讓人撕心裂肺地想吶喊。";
   Field fieldB = new Field("contents", fileTextB, Field.Store.YES,Field.Index.TOKENIZED);
   docB.add(fieldB);
  
   Document docC = new Document();
   String fileTextC = "我喜歡上了一個人孤獨地行遊,在夢與海洋的交接地帶熾烈燃燒着。"+
   "因爲,一條孤獨的魚喜歡上了火焰的顏色,真是荒唐地不合邏輯。";
   Field fieldC = new Field("contents", fileTextC, Field.Store.YES,Field.Index.TOKENIZED);
   docC.add(fieldC);
  
   writer.addDocument(docA);
   writer.addDocument(docB);
   writer.addDocument(docC);
   writer.optimize();
   writer.close();
}

public void search(String fieldName,String keyword) throws CorruptIndexException, IOException, ParseException{   // 檢索的方法,並實現高亮顯示
   searcher = new IndexSearcher(indexPath);
   QueryParser queryParse = new QueryParser(fieldName, analyzer);     //   構造QueryParser,解析用戶輸入的檢索關鍵字
   Query query = queryParse.parse(keyword);
   Hits hits = searcher.search(query);
   for(int i=0;i<hits.length();i++){
    Document doc = hits.doc(i);
    String text = doc.get(fieldName);
    SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");   
            Highlighter highlighter = new Highlighter(simpleHTMLFormatter,new QueryScorer(query));   
            highlighter.setTextFragmenter(new SimpleFragmenter(text.length()));      
            if (text != null) {   
                TokenStream tokenStream = analyzer.tokenStream(fieldName,new StringReader(text));   
                String highLightText = highlighter.getBestFragment(tokenStream, text);
                System.out.println("★高亮顯示第 "+(i+1) +" 條檢索結果如下所示:");
                System.out.println(highLightText);   
            }
   }
   searcher.close();
}


public static void main(String[] args) {    // 測試主函數
   MyHighLighter mhl = new MyHighLighter();
   try {
    mhl.createIndex();
    mhl.search("contents", "因爲");
   } catch (CorruptIndexException e) {
    e.printStackTrace();
   } catch (IOException e) {
    e.printStackTrace();
   } catch (ParseException e) {
    e.printStackTrace();
   }
}
}
程序說明:
1、createIndex()方法:使用ThesaurusAnalyzer分析器爲指定的文本建立索引。每個Document中都有一個name爲contents的Field。在實際應用中,可以再構造一一個name爲path的Field,指定檢索到的文件的路徑(本地路徑或者網絡上的鏈接地址)
2、根據已經建好的索引庫進行檢索。這首先需要解析用戶輸入的檢索關鍵字,使用QueryParser,必須與後臺使用的分析器相同,否則不能保證解析得到的查詢(由詞條構造)Query檢索到合理的結果集。
3、根據解析出來的Query進行檢索,檢索結果集保存在Hits中。遍歷,提取每個滿足條件的Document的內容,程序中直接把它的內容當作摘要內容,實現高亮顯示。在實際應用中,應該對應着一個提取摘要(或者檢索數據庫得到檢索關鍵字對應的結果集文件的摘要內容)的過程。有了摘要以後,就可以爲摘要內容增加高亮格式。
4、如果提取結果集文件的前N個字符串作爲摘要,只需要在 highlighter.setTextFragmenter(new SimpleFragmenter(text.length())); 中設置顯示摘要的字數,這裏顯示全部的文本作爲摘要。
運行程序,結果如下所示:
詞庫尚未被初始化,開始初始化詞庫.
初始化詞庫結束。用時:3906毫秒;
共添加195574個詞語。
★高亮顯示第 1 條檢索結果如下所示:
<font color='red'>因爲</font>火燒雲總是燃燒着消失在太陽衝下地平線的時刻,然後便是寧靜的自然的天籟,沒有誰會在這樣的時光的鏡片裏傷感自語,<font color='red'>因爲</font>燦爛給人以安靜的舒適感。
★高亮顯示第 2 條檢索結果如下所示:
<font color='red'>因爲</font>帶有以傷痕爲代價的美麗風景總是讓人不由地惴惴不安,緊接着襲面而來的抑或是病痛抑或是災難,沒有誰會能夠安逸着恬然,<font color='red'>因爲</font>模糊讓人撕心裂肺地想吶喊。
★高亮顯示第 3 條檢索結果如下所示:
我喜歡上了一個人孤獨地行遊,在夢與海洋的交接地帶熾烈燃燒着。<font color='red'>因爲</font>,一條孤獨的魚喜歡上了火焰的顏色,真是荒唐地不合邏輯。
上面的檢索結果在HTML網頁中,就會高亮顯示關鍵字“因爲”,顯示爲紅色。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章