zoukankan      html  css  js  c++  java
  • lucene搜索引擎高亮显示 highlight

    首先声明一下这篇文章大部分是转载自http://blog.csdn.net/java2king/article/details/4407998(好像也是转载,但是本人没有找到原创作者,在这里向他致敬),其中包含一些自己在操作过程中的出现的问题。

        首先在是我是在myeclipse下的开发的,“======”下是原文,文章写的很好很清楚,而且目前我还没有发现错误,所有遇到的问题都是我自己操作的问题。因为一直以来处理问题是先从简单的问题入手,然后一步一步的添加东西,也就是先用lucene把搜索引擎搭建起来,并在web端测试后,然后去添加高亮显示。在build path 里面加入lucene-highlighter-4.0.0-ALPHA.jar,我用的lucene的版本是lucene-4.0.0-ALPHA,lucene-highlighter-4.0.0-ALPHA.jar就在lucene解压后的文件夹中的highlighter文件夹下,导入包后,IndexSearch类在java application下运行很正常,可以部署到tomcat是就老师报没有找到相关类的异常,调试了很久,发现tomcat的lib里并没有lucene-highlighter-4.0.0-ALPHA.jar,然后就把lucene-highlighter-4.0.0-ALPHA.jar拷入tomcat的lib下,以web运行时,就显示LinkageError异常,后来鬼使神差的Deploy一下项目和server就可以使了。现在不太明白具体原因是什么,就先记录下来。

    ============================================================================================

    在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网页中,就会高亮显示关键字“因为”,显示为红色。

  • 相关阅读:
    tomcat bug之部署应用的时候经常会发上startup failed due to previous errors
    maven编译项目理解
    MyReport报表引擎2.6.5.0新功能
    PHP入门-摘要表格处理问题
    EnumMap源代码阅读器
    MySQL几种方法的数据库备份
    工作日志2014-08-19
    Linux通过网卡驱动程序和版本号的信息
    JS于,子类调用父类的函数
    hdu 5007 水 弦
  • 原文地址:https://www.cnblogs.com/redlight/p/3073021.html
Copyright © 2011-2022 走看看