夢幻e家人

          java咖啡
          隨筆 - 15, 文章 - 0, 評論 - 11, 引用 - 0
          數(shù)據(jù)加載中……

          2008年7月8日

          Lucene關(guān)鍵字高亮顯示

          Lucene關(guān)鍵字高亮顯示
           
           

          在Lucene的org.apache.lucene.search.highlight包中提供了關(guān)于高亮顯示檢索關(guān)鍵字的工具。使用百度、Google搜索的時候,檢索結(jié)果顯示的時候,在摘要中實現(xiàn)與關(guān)鍵字相同的詞條進(jìn)行高亮顯示,百度和Google指定紅色高亮顯示。

          有了Lucene提供的高亮顯示的工具,可以很方便地實現(xiàn)高亮顯示的功能。

          高亮顯示,就是根據(jù)用戶輸入的檢索關(guān)鍵字,檢索找到該關(guān)鍵字對應(yīng)的檢索結(jié)果文件,提取對應(yīng)于該文件的摘要文本,然后根據(jù)設(shè)置的高亮格式,將格式寫入到摘要文本中對應(yīng)的與關(guān)鍵字相同或相似的詞條上,在網(wǎng)頁上顯示出來,該摘要中的與關(guān)鍵字有關(guān)的文本就會以高亮的格式顯示出來。

          Lucene中org.apache.lucene.search.highlight.SimpleHTMLFormatter類可以構(gòu)造一個高亮格式,這是最簡單的構(gòu)造方式,例如:

          SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");

          構(gòu)造方法聲明為public SimpleHTMLFormatter(String preTag, String postTag),因為這種高亮格式是依賴于網(wǎng)頁文件的,HTML文件中是以標(biāo)記(tag)來標(biāo)識的,即存在一個preTag和一個postTag。

          上面構(gòu)造的高亮格式是摘要中出現(xiàn)的關(guān)鍵字使用紅色來顯示,區(qū)分其它文本。

          通過構(gòu)造好的高亮格式對象,來構(gòu)造一個org.apache.lucene.search.highlight.Highlighter實例,然后根據(jù)對檢索結(jié)果得到的Field的文本內(nèi)容(這里是指摘要文本)進(jìn)行切分,找到與檢索關(guān)鍵字相同或相似的詞條,將高亮格式加入到摘要文本中,返回一個新的、帶有格式的摘要文本,在網(wǎng)頁上就可以呈現(xiàn)高亮顯示。

          下面實現(xiàn)一個簡單的例子,展示實現(xiàn)高亮顯示的處理過程。

          測試類如下所示:

          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 = "因為帶有以傷痕為代價的美麗風(fēng)景總是讓人不由地惴惴不安,緊接著襲面而來的抑或是病痛抑或是災(zāi)難,沒有誰會能夠安逸著恬然,因為模糊讓人撕心裂肺地想?yún)群啊?;
             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{   // 檢索的方法,并實現(xiàn)高亮顯示
             searcher = new IndexSearcher(indexPath);
             QueryParser queryParse = new QueryParser(fieldName, analyzer);     //   構(gòu)造QueryParser,解析用戶輸入的檢索關(guān)鍵字
             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) +" 條檢索結(jié)果如下所示:");
                          System.out.println(highLightText);   
                      }
             }
             searcher.close();
          }


          public static void main(String[] args) {    // 測試主函數(shù)
             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。在實際應(yīng)用中,可以再構(gòu)造一一個name為path的Field,指定檢索到的文件的路徑(本地路徑或者網(wǎng)絡(luò)上的鏈接地址)

          2、根據(jù)已經(jīng)建好的索引庫進(jìn)行檢索。這首先需要解析用戶輸入的檢索關(guān)鍵字,使用QueryParser,必須與后臺使用的分析器相同,否則不能保證解析得到的查詢(由詞條構(gòu)造)Query檢索到合理的結(jié)果集。

          3、根據(jù)解析出來的Query進(jìn)行檢索,檢索結(jié)果集保存在Hits中。遍歷,提取每個滿足條件的Document的內(nèi)容,程序中直接把它的內(nèi)容當(dāng)作摘要內(nèi)容,實現(xiàn)高亮顯示。在實際應(yīng)用中,應(yīng)該對應(yīng)著一個提取摘要(或者檢索數(shù)據(jù)庫得到檢索關(guān)鍵字對應(yīng)的結(jié)果集文件的摘要內(nèi)容)的過程。有了摘要以后,就可以為摘要內(nèi)容增加高亮格式。

          4、如果提取結(jié)果集文件的前N個字符串作為摘要,只需要在 highlighter.setTextFragmenter(new SimpleFragmenter(text.length())); 中設(shè)置顯示摘要的字?jǐn)?shù),這里顯示全部的文本作為摘要。

          運行程序,結(jié)果如下所示:

          詞庫尚未被初始化,開始初始化詞庫.
          初始化詞庫結(jié)束。用時:3906毫秒;
          共添加195574個詞語。
          ★高亮顯示第 1 條檢索結(jié)果如下所示:
          <font color='red'>因為</font>火燒云總是燃燒著消失在太陽沖下地平線的時刻,然后便是寧靜的自然的天籟,沒有誰會在這樣的時光的鏡片里傷感自語,<font color='red'>因為</font>燦爛給人以安靜的舒適感。
          ★高亮顯示第 2 條檢索結(jié)果如下所示:
          <font color='red'>因為</font>帶有以傷痕為代價的美麗風(fēng)景總是讓人不由地惴惴不安,緊接著襲面而來的抑或是病痛抑或是災(zāi)難,沒有誰會能夠安逸著恬然,<font color='red'>因為</font>模糊讓人撕心裂肺地想?yún)群啊?br /> ★高亮顯示第 3 條檢索結(jié)果如下所示:
          我喜歡上了一個人孤獨地行游,在夢與海洋的交接地帶熾烈燃燒著。<font color='red'>因為</font>,一條孤獨的魚喜歡上了火焰的顏色,真是荒唐地不合邏輯。

          上面的檢索結(jié)果在HTML網(wǎng)頁中,就會高亮顯示關(guān)鍵字“因為”,顯示為紅色。

          posted @ 2008-08-06 11:24 軒轅 閱讀(207) | 評論 (0)編輯 收藏

          Lucene關(guān)鍵字高亮顯示

          package searchfileexample;

          import javax.servlet.*;
          import javax.servlet.http.*;
          import java.io.*;
          import java.io.IOException;
          import java.io.StringReader;

          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;
          import org.apache.lucene.analysis.standard.StandardAnalyzer;


          public class MyHighLighterServlet extends HttpServlet {
            private static final String CONTENT_TYPE = "text/html; charset=GB18030";

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

            //Initialize global variables
            public void init() throws ServletException {
              analyzer = new StandardAnalyzer();
            }
            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 = "因為帶有以傷痕為代價的美麗風(fēng)景總是讓人不由地惴惴不安,緊接著襲面而來的抑或是病痛抑或是災(zāi)難,沒有誰會能夠安逸著恬然,因為模糊讓人撕心裂肺地想?yún)群啊?;
                 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,PrintWriter out) throws CorruptIndexException, IOException, ParseException{   // 檢索的方法,并實現(xiàn)高亮顯示
                 searcher = new IndexSearcher(indexPath);
                 QueryParser queryParse = new QueryParser(fieldName, analyzer);     //   構(gòu)造QueryParser,解析用戶輸入的檢索關(guān)鍵字
                 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) +" 條檢索結(jié)果如下所示:");
                              out.println(highLightText);   
                          }
                 }
                 searcher.close();
              }

            //Process the HTTP Get request
            public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              response.setContentType(CONTENT_TYPE);
              PrintWriter out = response.getWriter();
              out.println("<html>");
              out.println("<head><title>MyHighLighterServlet</title></head>");
              out.println("<body bgcolor=\"#ffffff\">");

            
               try {
                createIndex();
                search("contents", "因為",out);
               } catch (CorruptIndexException e) {
                e.printStackTrace();
               } catch (IOException e) {
                e.printStackTrace();
               } catch (ParseException e) {
                e.printStackTrace();
               }

             
             
             
              out.println("</body></html>");
            }

            //Clean up resources
            public void destroy() {
            }
          }

          posted @ 2008-08-06 11:22 軒轅 閱讀(866) | 評論 (0)編輯 收藏

          _blank _self的含義

          _blank -- 打開一個新窗體
          _parent -- 在父窗體中打開
          _self -- 在本頁打開,此為默認(rèn)值
          _top -- 在上層窗體中打開
          _search --同時打開搜索窗口

          一個對應(yīng)的框架頁的名稱 -- 在對應(yīng)框架頁中打開

          posted @ 2008-07-08 10:23 軒轅 閱讀(209) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 烟台市| 灵石县| 东丰县| 淮南市| 迁西县| 苍南县| 邵东县| 吕梁市| 农安县| 宝清县| 敖汉旗| 克什克腾旗| 石林| 应用必备| 淄博市| 托克逊县| 宁蒗| 佛山市| 西丰县| 任丘市| 长宁县| 德安县| 六枝特区| 兖州市| 海盐县| 崇信县| 平舆县| 福贡县| 镇江市| 纳雍县| 略阳县| 涟水县| 泰宁县| 保靖县| 崇州市| 南岸区| 西峡县| 夹江县| 岳阳市| 上栗县| 兴隆县|