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

  • 相关阅读:
    Compression algorithm (deflate)
    tcpip数据包编码解析(chunk and gzip)_space of Jialy_百度空间
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    gzip压缩算法: gzip 所使用压缩算法的基本原理
    Decompressing a GZip Stream with Zlib
    Frequently Asked Questions about zlib
    how to decompress gzip stream with zlib
    自己动手写web服务器四(web服务器是如何通过压缩数据,web服务器的gzip模块的实现)
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    C语言抓http gzip包并解压 失败 C/C++ ChinaUnix.net
  • 原文地址:https://www.cnblogs.com/redlight/p/3073021.html
Copyright © 2011-2022 走看看