如何使用lucene 索引文件合并对html文件进行索引

Lucene&--&介绍及索引机制
Lucene 简介
Lucene 是一个基于 Java
的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache
Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
目前已经有很多应用程序的搜索功能是基于 Lucene
的,比如 Eclipse 的帮助系统的搜索功能。Lucene
能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。
比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和
PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene
进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使
Lucene 能够几乎适用于所有的搜索应用程序。
索引和搜索
索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。
为什么索引这么重要呢,试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。
Lucene 采用的是一种称为反向索引(inverted index)的机制。反向索引就是说我们维护了一个词 /
短语表,对于这个表中的每个词 / 短语,都有一个链表描述了有哪些文档包含了这个词 /
短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。
对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。
Lucene 使用各种解析器对各种不同类型的文档进行解析。比如对于 HTML 文档,HTML
解析器会做一些预处理的工作,比如过滤文档中的 HTML 标签等等。HTML 解析器的输出的是文本内容,接着 Lucene
的分词器(Analyzer)从文本内容中提取出索引项以及相关信息,比如索引项的出现频率。接着 Lucene
的分词器把这些信息写到索引文件中。
实例: 用Lucene索引文档
只要你能将要索引的文件转化成文本格式,Lucene 就能为你的文档建立索引。比如,如果你想为 HTML 文档或者 PDF
文档建立索引,那么首先你就需要从这些文档中提取出文本信息,然后把文本信息交给 Lucene 建立索引。我们接下来的例子用来演示如何利用
Lucene 为后缀名为 txt 的文件建立索引。
1. 准备文本文件
首先把一些以 txt 为后缀名的文本文件放到一个目录中,比如在 Windows 平台上,你可以放到
C:\\files_to_index 下面。
2. 创建索引
下面是为我们所准备的文档创建索引的代码。
Lucene 索引你的文档
package lucene.
import java.io.FileR
import java.io.R
import java.util.D
org.apache.lucene.analysis.A
org.apache.lucene.analysis.standard.StandardA
org.apache.lucene.document.D
org.apache.lucene.document.F
org.apache.lucene.index.IndexW
class TextFileIndexer {
&public static void
main(String[] args) throws Exception{
& &//fileDir
is the directory that contains the text files to be
& fileDir &= new
File("C:\\files_to_index ");
&//indexDir is the directory that hosts Lucene's
index files
& indexDir = new
File("C:\\luceneIndex");
& &Analyzer
luceneAnalyzer = new StandardAnalyzer();
&IndexWriter indexWriter = new
IndexWriter(indexDir,luceneAnalyzer,true);
textFiles &=
fileDir.listFiles();
startTime = new Date().getTime();
&//Add documents to the index
& &for(int i
= 0; i & textFiles. i++){
&if(textFiles[i].isFile() &&
textFiles[i].getName().endsWith(".txt")){
& &System.out.println("File " +
textFiles[i].getCanonicalPath()&
& & + " is being
indexed");
& &Reader textReader = new
FileReader(textFiles[i]);
& &Document document = new
Document();
&document.add(Field.Text("content",textReader));
&document.add(Field.Text("path",textFiles[i].getPath()));
&indexWriter.addDocument(document);
&indexWriter.optimize();
&indexWriter.close();
endTime = new Date().getTime();
&System.out.println("It took " + (endTime -
startTime)&
& & + " milliseconds to create an
index for the files in the directory "
fileDir.getPath());
如上所示,你可以利用 Lucene
非常方便的为文档创建索引。
接下来我们分析一下清单1中的比较关键的代码,我们先从下面的一条语句开始看起。
开始看起。
Analyzer luceneAnalyzer = new StandardAnalyzer();
这条语句创建了类 StandardAnalyzer 的一个实例,这个类是用来从文本中提取出索引项的。它只是抽象类 Analyzer
的其中一个实现。Analyzer 也有一些其它的子类,比如 SimpleAnalyzer 等。
我们接着看另外一条语句:
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);
这条语句创建了类 IndexWriter 的一个实例,该类也是 Lucene
索引机制里面的一个关键类。这个类能创建一个新的索引或者打开一个已存在的索引并为该所引添加文档。我
们注意到该类的构造函数接受三个参数,第一个参数指定了存储索引文件的路径。第二个参数指定了在索引过程中使用什么样的分词器。最后一个参数是个布尔变量,如果值为真,那么就表示要创建一个新的索引,如果值为假,就表示打开一个已经存在的索引。
接下来的代码演示了如何添加一个文档到索引文件中。
Document document = new Document();&
document.add(Field.Text("content",textReader));
document.add(Field.Text("path",textFiles[i].getPath()));&
indexWriter.addDocument(document);
首先第一行创建了类 Document
的一个实例,它由一个或者多个的域(Field)组成。你可以把这个类想象成代表了一个实际的文档,比如一个 HTML 页面,一个 PDF
文档,或者一个文本文件。而类 Document 中的域一般就是实际文档的一些属性。比如对于一个 HTML
页面,它的域可能包括标题,内容,URL 等。
我们可以用不同类型的 Field 来控制文档的哪些内容应该索引,哪些内容应该存储。
代码的第二行和第三行为文档添加了两个域,每个域包含两个属性,分别是域的名字和域的内容。在我们的例子中两个域的名字分别是"content"和"path"。分别存储了我们需要索引的文本文件的内容和路径。
最后一行把准备好的文档添加到了索引当中。
当我们把文档添加到索引中后,不要忘记关闭索引,这样才保证 Lucene
把添加的文档写回到硬盘上。下面的一句代码演示了如何关闭索引。
indexWriter.close();
接下来我们看看对索引进行的另外一种重要的操作,从索引中删除文档。
从索引中删除文档
类IndexReader负责从一个已经存在的索引中删除文档
& indexDir = new
File("C:\\luceneIndex");
IndexReader
ir = IndexReader.open(indexDir);
ir.delete(1);
ir.delete(new
Term("path","C:\\file_to_index\lucene.txt"));
ir.close();
第二行用静态方法 IndexReader.open(indexDir) 初始化了类 IndexReader
的一个实例,这个方法的参数指定了索引的存储路径。
类 IndexReader
提供了两种方法去删除一个文档,如程序中的第三行和第四行所示。第三行利用文档的编号来删除文档。每个文档都有一个系统自动生成的编号。
第四行删除了路径为"C:\\file_to_index\lucene.txt"的文档。你可以通过指定文件路径来方便的删除一个文档。值得注意的是虽然利用上述代码删除文档使得该文档不能被检索到,但是并没有物理上删除该文档。Lucene
只是通过一个后缀名为 .delete 的文件来标记哪些文档已经被删除。
既然没有物理上删除,我们可以方便的把这些标记为删除的文档恢复过来,首先打开一个索引,然后调用方法 ir.undeleteAll()
来完成恢复工作。
恢复已删除文档
File & indexDir = new
File("C:\\luceneIndex");
IndexReader ir = IndexReader.open(indexDir);
ir.undeleteAll();
ir.close();
你现在也许想知道如何物理上删除索引中的文档,方法也非常简单。
如何物理上删除文档
File & indexDir = new
File("C:\\luceneIndex");
Analyzer luceneAnalyzer = new StandardAnalyzer();
IndexWriter indexWriter = new
IndexWriter(indexDir,luceneAnalyzer,false);
indexWriter.optimize();
indexWriter.close();
第三行创建了类 IndexWriter 的一个实例,并且打开了一个已经存在的索引。第 4
行对索引进行清理,清理过程中将把所有标记为删除的文档物理删除。
没有直接提供方法对文档进行更新,如果你需要更新一个文档,那么你首先需要把这个文档从索引中删除,然后把新版本的文档加入到索引中去。
提高索引性能
Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中。为了解决这个问题,
Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?幸运的是,Lucene 的类 IndexWriter
提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。
1.合并因子(mergeFactor)
这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如,如果合并因子的值是
10,那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且,如果磁盘上的索引块的隔数达到 10
的话,这 10 个索引块会被合并成一个新的索引块。这个参数的默认值是
10,如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲,为这个参数赋一个比较大的值会得到比较好的索引效果。
2.最小合并文档数
这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10,如果你有足够的内存,那么将这个值尽量设的比较大一些将会显著的提高索引性能。
3.最大合并文档数
这个参数决定了一个索引块中的最大的文档数。它的默认值是
Integer.MAX_VALUE,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。
提高索引性能
public class AdvancedTextFileIndexer &{
& public static void main(String[] args)
throws Exception{
& & //fileDir is the
directory that contains the text files to be indexed
& & File &
fileDir &= new File("C:\\files_to_index");
& & //indexDir is the
directory that hosts Lucene's index files
& & File &
indexDir = new File("C:\\luceneIndex");
& & Analyzer luceneAnalyzer
= new StandardAnalyzer();
& & File[] textFiles
&= fileDir.listFiles();
& & long startTime = new
Date().getTime();
& & int mergeFactor =
& & int minMergeDocs =
& & int maxMergeDocs =
Integer.MAX_VALUE;
& & IndexWriter indexWriter
= new IndexWriter(indexDir,luceneAnalyzer,true); &
& & indexWriter.mergeFactor
& & indexWriter.minMergeDocs
= minMergeD
& & indexWriter.maxMergeDocs
= maxMergeD
& & //Add documents to the
& & for(int i = 0; i &
textFiles. i++){
if(textFiles[i].isFile() &&
textFiles[i].getName().endsWith(".txt")){
& Reader textReader = new
FileReader(textFiles[i]);
& Document document = new Document();
document.add(Field.Text("content",textReader));
document.add(Field.Keyword("path",textFiles[i].getPath()));
& indexWriter.addDocument(document);
indexWriter.optimize();
indexWriter.close();
& & long endTime = new
Date().getTime();
System.out.println("MergeFactor: " +
indexWriter.mergeFactor);
System.out.println("MinMergeDocs: " +
indexWriter.minMergeDocs);
System.out.println("MaxMergeDocs: " +
indexWriter.maxMergeDocs);
System.out.println("Document number: " + textFiles.length);
& & System.out.println("Time
consumed: " + (endTime - startTime) + " milliseconds");
通过这个例子,我们注意到在调整缓冲区的大小以及写磁盘的频率上面 Lucene
给我们提供了非常大的灵活性。现在我们来看一下代码中的关键语句。如下的代码首先创建了类 IndexWriter
的一个实例,然后对它的三个参数进行赋值。
int mergeFactor = 10;&
int minMergeDocs = 10;&
int maxMergeDocs = Integer.MAX_VALUE;&
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);&
&indexWriter.mergeFactor = mergeF&
indexWriter.minMergeDocs = minMergeD&
indexWriter.maxMergeDocs = maxMergeD
下面我们来看一下这三个参数取不同的值对索引时间的影响,注意参数值的不同和索引之间的关系。我们为这个实验准备了 10000
个测试文档。表 1 显示了测试结果。
表1:测试结果
<img ALT="表1:测试结果" BORDER="0" src="/blog7style/images/common/sg_trans.gif" real_src ="/developerworks/cn/java/wa-lucene/images/table1.gif" WIDTH="502" STYLE="margin: 0 padding: 0 outline: 0 font-size: 13 vertical-align: font-family: Arial, sans- line-height: 15 background-color: rgb(255, 255, 255);" NAME="image_operate_41825"
TITLE="Lucene&--&介绍及索引机制" />
通过表1,你可以清楚地看到三个参数对索引时间的影响。在实践中,你会经常的改变合并因子和最小合并文档数的值来提高索引性能。只要你有足够大的内存,你可以为合并因子和最小合并文档数这两个参数赋尽量大的值以提高索引效率,另外我们一般无需更改最大合并文档数这个参数的值,因为系统已经默认将它设置成了最大。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。基于Lucene和HTMLParser技术的搜索引擎的设计与实现_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
基于Lucene和HTMLParser技术的搜索引擎的设计与实现
||文档简介
计算机硕士研究生|
总评分4.6|
浏览量40099
&&n&#8203;u&#8203;t&#8203;c&#8203;h&#8203;,&#8203;L&#8203;u&#8203;c&#8203;e&#8203;n&#8203;e&#8203;,&#8203;P&#8203;a&#8203;g&#8203;e&#8203;R&#8203;a&#8203;n&#8203;k&#8203;,&#8203;搜&#8203;索&#8203;引&#8203;擎
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩53页未读,继续阅读
你可能喜欢下次自动登录
现在的位置:
& 综合 & 正文
Lucene索引前对doc pdf html文件的预处理
初学Lucene,写下点小小的心得:
Lucene提供的API能够方便地对文本文档创建索引,但当需要为像.doc 、.pdf 这样的非文本文档创建索引时就必须先把文档转换为纯文本。
对.pdf文件的处理
lib:PDFBox
PDFBox是一个在java环境中对pdf文件进行解析处理的开源软件,同时它也提供了一个丰富的类库支持对pdf文件的操作。PDFBox为使
用Lucene的开发者专门提供了LucenePDFDocument类,它的static方法getDocument(ps:该方法被重载三次)能够直
接返回一个Lucene的Document类型结果。所以在为一个pdf文件(例子中为File类型实例pdfFile)创建索引时只要写下如下语句就可
LucenePDFDocument.getDocument(pdfFile);
getDocument方法的这种形式很好,接下来对.doc以及对.html文件的处理也参照这种形式。
对.doc文件的处理
lib:tm-extractors-0.4
这原是Apache的POI类库的一部分——HWPF,POI提供了一组操作MS-word/excel等文件的方法,在最近的release版本
中HWPF被移出,需要下载独立的tm-extractors-0.4。下面的中实现了static方法getDocument(File)返回
Lucene的Document类型结果,主要通过调用WordExtractor类的成员方法extractor,该方法能返回一个包含所解析doc文
件内容的String类型实例。
LuceneDOCDocument
Document getDocument(File doc)
String docPath
doc.getAbsolutePath();
String title
doc.getName();
InputStream inputStream
Reader contents
Document document
Document();
inputStream
FileInputStream(doc);
(FileNotFoundException e)
e.printStackTrace();
WordExtractor extractor
WordExtractor();
StringReader(extractor.extractText(inputStream));
(Exception e)
e.printStackTrace();
document.add(
, title, Field.Store.YES, Field.Index.TOKENIZED));
document.add(
, contents));
document.add(
, docPath, Field.Store.YES, Field.Index.NO));
HTML文件虽然是文本,但是由于其中包含的标记无法被Lucene识别,导致也会被编入索引,而用户在搜索时并不希望搜索到这些标签,所以在对HTML文件创建所以前必须对其进行去标签的处理。
对HTML的处理(去标签)
lib:htmlparser
原本Lucene的DEMO中也附带了一个HtmlParser,只是这个html解析器功能比较弱。另外不知道是不是笔者使用上的错误,在使用索
引文件管理器Luke查看时发现,DEMO带的HtmlParser的成员方法getReader所返回的字符流的内容并非是html文件的全部文本内
容,而仅仅是标题内容。
在下面的例子中,笔者使用了更为强大的htmlparser,同样在代码中定义了static方法getDocument(File)返回Document类型。
LuceneHTMLDocument
Document getDocument(File html)
String htmlPath
html.getAbsolutePath();
String text
Parser parser
Parser(htmlPath);
(ParserException e)
e.printStackTrace();
parser.setEncoding(
(ParserException e)
e.printStackTrace();
HtmlPage visitor
HtmlPage(parser);
parser.visitAllNodesWith(visitor);
(ParserException e)
e.printStackTrace();
NodeList nodes
visitor.getBody();
nodes.size();
nodes.elementAt(i);
node.toPlainTextString();
String title
visitor.getTitle();
Reader contents
StringReader (text);
Document document
Document();
document.add(
, title, Field.Store.YES, Field.Index.TOKENIZED));
document.add(
, contents));
document.add(
, htmlPath, Field.Store.YES, Field.Index.NO));
&&&&推荐文章:
【上篇】【下篇】如何使用Lucene对html文件进行索引_百度知道
如何使用Lucene对html文件进行索引
提问者采纳
Index.Store.Open(new DirectoryInfo(IndexPath)).NOT_ANALYZED));createdon&quot,tags&quot, GetContentSummary(model).Index.Id;;
document.YES.Add(new Field(&;{0}&#39.Add(new Field(&quot.Content.Add(new Field(&quot, Field.Title, false.ToString();
catch (Exception ex)
if (!ApplicationSAn error occured while adding page &#39,createdby&quot, model.AddDocument(document), &quot,先正则过滤掉HTML标记, Field.CreatedOn.Store.ANALYZED))。索引public virtual void Add(PageViewModel model)
EnsureDirectoryExists().YES.Add(new Field(&quot,;
using (IndexWriter writer = new IndexWriter(FSDirectory.S
document.S
document, Field, model, Field.IgnoreSearchIndexErrors)
throw new SearchException(ex, model.Add(new Field(&quot,和普通文件一样的操作, Field.YES.Index.Store.Content, Field, Field,.UNLIMITED))
Document document = new Document().SpaceDelimitedTags().Index.S.Index.ANALYZED));
document.YES;, Field, Field.Index.MaxFieldL.ToShortDateString().ToString();
StandardAnalyzer analyzer = new StandardAnalyzer(LUCENEVERSION);content&quot.NO)).Length, Fcontentlength&quot.YES;
writer, Field.I
document.Store.NO)), IndexWriter.Add(new Field(&quot, F
document.Add(new Field(&quot, Field.Add(new Field(& to the search index&quot.ANALYZED));contentsummary&.ANALYZED)), Field,只取内容.YES;title&id&quot.Store.NOT_ANALYZED)).Optimize();
writer, model.YES.YES.Index, Field.Title), Field.CreatedBy;
来自团队:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁如何对网站的Html文件进行全文检索,搜索结果就象Google返回的结果一样
[问题点数:100分,结帖人yuanhang1977]
如何对网站的Html文件进行全文检索,搜索结果就象Google返回的结果一样
[问题点数:100分,结帖人yuanhang1977]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2007年9月 .NET技术大版内专家分月排行榜第二2007年8月 .NET技术大版内专家分月排行榜第二
2009年7月 荣获微软MVP称号2010年7月 荣获微软MVP称号2008年7月 荣获微软MVP称号
2007年8月 .NET技术大版内专家分月排行榜第一2007年7月 .NET技术大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。}

我要回帖

更多关于 lucene删除索引文件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信