天天看點

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個詞語。

繼續閱讀