Lucene加中文分词paoding调研结果
来源:互联网 发布:软件过程可视性 编辑:程序博客网 时间:2024/05/01 11:23
Lucene加中文分词paoding调研结果
因为项目原因,调研了下全文检索。网上开源的最流行的检索好像是lucene,nutch据说是稳定性有待测试,所以没试。需要说明的是我要做的这个全文检索是搜索本项目的文档,网页和数据库内容,不涉及到web上网页的搜索。
Lucene介绍的文章很多,重点的都看了,原理不明白的可以看下以下:
http://www.ibm.com/developerworks/cn/java/wa-lucene/
自己参照别人的写了个例子。我用的是lucene2.3.1版本,这里需要注意版本不一样的话写的代码就有所区别,网上很多例子都不是参照新版的写的,不能直接用。
import org.apache.lucene.index.IndexWriter;
import java.io.File;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
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.Searcher;
import java.io.FileReader;
import org.apache.lucene.document.*;
import org.apache.lucene.store.*;
import net.paoding.analysis.analyzer.PaodingAnalyzer;
import java.io.*;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
public class Mp3Searcher {
private String DATA_DIR ; //文件的目录(如果是对文件进行索引的话)
private String index_DIR ;//存放索引的目录
private RAMDirectory directory ;
private PaodingAnalyzer analyzer = null;
//private Analyzer analyzer = null;
public Mp3Searcher(){
//Analyzer analyzer = new PaodingAnalyzer();
}
public String getindedxdir()
{
return this.index_DIR;
}
public void buildIndex() throws IOException{
String DATA_DIR="C://lucenetest//index"; //存放文件目录
String index_DIR="E://test"; //存放索引文件目录
File data_Dir = new File(DATA_DIR);
File index_Dir = new File(index_DIR);
this.index_DIR=index_DIR;
Analyzer analyzer = new PaodingAnalyzer();
//Analyzer analyzer = new StandardAnalyzer();
File[] dataFiles = data_Dir.listFiles();
boolean fileIsExist = false;
if (index_Dir.listFiles().length == 0)
fileIsExist = true;
IndexWriter writer = new IndexWriter(index_Dir, analyzer, fileIsExist);
try{
this.doIndex(dataFiles,writer);
}catch(Exception e)
{
e.printStackTrace();
}
writer.optimize();
writer.close();
}
private void doIndex(File[] dataFiles, IndexWriter indexWriter) throws Exception {
for (int i = 0; i < dataFiles.length; i++) {
if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".htm"))
{//索引所有htm格式文件
System.out.println("Indexing file " + dataFiles[i].getCanonicalPath());
Reader txtReader = new FileReader(dataFiles[i]);
Document document = new Document();
document.add(new Field("path", dataFiles[i].getCanonicalPath(), Field.Store.YES,Field.Index.UN_TOKENIZED));
document.add(new Field("filename", dataFiles[i].getName(), Field.Store.YES, Field.Index.TOKENIZED));
document.add(new Field("contents", txtReader));
indexWriter.addDocument(document);
}
else if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".doc"))
{
FileInputStream in = new FileInputStream(dataFiles[i]);//获得文件流
WordExtractor extractor = new WordExtractor(in);//使用POI对word文件进行解析
String str = extractor.getText();//返回String
Document document = new Document();//生成Document对象,其中有3个Field,分别是path,filename,contents
document.add(new Field("path", dataFiles[i].getCanonicalPath(), Field.Store.YES,Field.Index.UN_TOKENIZED));
document.add(new Field("filename", dataFiles[i].getName(), Field.Store.YES, Field.Index.TOKENIZED));
document.add(new Field("contents", str, Field.Store.YES,Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS));
System.out.print(document.getField("path").toString()+document.getField("filename").toString()+document.getField("contents").toString());
indexWriter.addDocument(document);
}
else if (dataFiles[i].isDirectory())
doIndex(dataFiles[i].listFiles(), indexWriter);//使用递归,继续索引文件夹
}
}
// public void searchIndex(String curcontents,String curfilename) throws Exception {
public void searchIndex(String curcontents) throws Exception {
String contents = curcontents;//内容的关键字
// String filename = curfilename;//文件名的关键字
File indexDir = new File(index_DIR);//存放索引的文件夹
FSDirectory directory = FSDirectory.getDirectory(indexDir);
Searcher searcher = new IndexSearcher(directory);
Analyzer analyzer = new PaodingAnalyzer();
//Analyzer analyzer = new StandardAnalyzer();
QueryParser parserContents = new QueryParser("contents", analyzer);
Query query1 = parserContents.parse(contents);
// QueryParser parserFilename = new QueryParser("filename", analyzer); //使用同一个分析器luceneAnalyzer分别生成两个QueryParser对象
// Query query2 = parserFilename.parse(filename);
BooleanQuery query = new BooleanQuery();
query.add(query1, BooleanClause.Occur.MUST);
// query.add(query2, BooleanClause.Occur.MUST);
//SimpleHTMLFormatter formatter =new SimpleHTMLFormatter("<span class=/"highlight/">","</span>");
// SimpleHTMLFormatter formatter =new SimpleHTMLFormatter();
// Highlighter highlighter = new Highlighter(formatter,new QueryScorer(query));
Highlighter highlighter = new Highlighter(new QueryScorer(query));
highlighter.setTextFragmenter(new SimpleFragmenter(60)); //Lucene自带的高亮功能
Hits hits = searcher.search(query);
for(int i=0;i<hits.length();i++){
Document doc=hits.doc(i);
System.out.println("检索文件"+doc.get("path"));
String contents1=doc.get("contents");
if (contents1!=null)
{
TokenStream tokenStream = analyzer.tokenStream("contents", new StringReader(contents1));
String str = highlighter.getBestFragment(tokenStream,hits.doc(i).get("contents"));
System.out.println(str);
}
}
}
public static void main(String[] args) throws Exception
{
Mp3Searcher searcher=new Mp3Searcher();
String DATA_DIR="C://lucenetest//index";
String index_DIR="E://test";
searcher.buildIndex();
//searcher.searchIndex("lucene","绝缘材料");
searcher.searchIndex("索引");
}
}
以上代码已经在eclipse3.2上测试通过,建的是java项目。代码中有些注释的部分也是能用的,稍微修改下就行。
下面重点说下中文分词。因为lucene是老外写的,所以它对英文,德文等支持比较好。对于中文的功能是比较弱的。中文分词要用standardanalyzer,这个是采用二元分词法,分词效果不理想,所以国人也开发了很多中文分词的软件。网上很有名的就是中科院的,可是中科院的这个是c写的,也有人把它改为java,但是据说bug很多,所以我也没下。我稍微看了下好像是说中科院的这个分词的dll要用jni用在lucene.net这个版本上,但是这个版本已经旧了,所以我没调研。其他的中文分词软件我主要看了下庖丁解牛分词软件。
首先说明这个软件在java项目中是可以使用的,问题主要在web项目中。
http://paoding.googlecode.com/svn/trunk/paoding-analysis/
最好是下svn上的,因为这个是更新过的,更改了2.0.4版的一些bug。
http://groups.google.com/group/paoding/topics?start=20&sa=N是论坛
网上也有各种出现的各种错误,主要是如下的,我都碰到过:
首先是需要设置Paoding词典到我们的系统环境变量,该词典就在Paoding的dic 文件夹里,把它设置到环境变量中,变量名是PAODING_DIC_HOME,这里要注意:DIC的路径不能包含中文,标点,空格...
然后,再使用的时候,你需要将Paoding的5个jar包拷贝到你的工程中去,但是要注意你工程的路径,如果你发布的是WEB工程,记得你的服务器路径也不能包含中文空格,之前我的路径是
g:/Tomcat 6.0就不行,被迫改成了g:/Tomcat
如果上面设置没问题,就可以使用Paoding进行搜索开发了,但是在建立索引的时候你可能还会遇到 java.io.File.setWritable(Z)Z异常问题,这个一般是你JDK的问题,升级下你JDK的版本.
我就遇到过很奇怪的问题,我使用JDK1.5一直没问题,但是有一天突然爆了这个错误,让我郁闷,最后升级了个JDK,问题就解决了....
以上是网上别人反应的问题,我自己碰到的问题主要是这几个:
1. Classpath的路径paoding总是不识别,导致无法正确加载词库。无论在properties文件中如何设置都搞不好,也许是jdk版本问题,我用的是1.5的。这样导致在部署到tomcat5.0时总是报路径不对。
2. 我建了个jsp和servlet,将结果显示在servlet中。结果发现在jsp页面上输入中文关键字时页面无任何结果,但是搜英文的就有结果。
这个问题很多人看了都认为是个乱码处理问题,但是我调了很久,各种方式都试了,仍然不行。网上也有人反映和我一样的问题,但是没有解决办法。
这两个重大问题导致我放弃了paoding,还有一点是分词软件是需要维护的,网上的成功的基于lucene的网站如jlive等,我想它们可能是购买的某公司的中文分词的解析器来做搜索的。
备注:本人编程能力比较差,暂时只能认识到这个层次。
- Lucene加中文分词paoding调研结果
- Lucene中文分词Paoding
- Lucene中使用Paoding中文分词
- paoding 中文分词学习
- Paoding中文分词参考手册
- lucene 结合paoding分词器
- 基于Lucene的搜索系统 同时使用Paoding进行中文分词 一
- 基于Lucene的搜索系统 同时使用Paoding进行中文分词 二
- Nutch 分词 中文分词 paoding 疱丁
- paip.中文 分词 ---paoding 3.1 的使用
- lucene查看分词结果
- Lucene查看分词结果
- Lucene-----查看分词结果
- 关于Lucene.net中文分词后的结果着色问题
- Lucene中如何使用庖丁Paoding Analyzer分词器
- 搜索引擎分词:Nutch整合Paoding中文分词步骤详解
- 搜索引擎分词:Nutch整合Paoding中文分词步骤详解
- Lucene中文分词
- sqlserver日志文件总结及充满处理
- getAttribute()和getParameter()区别
- Don't say goodbye
- SQL Server 连接基础知识
- 将SQL Server中所有表的列信息显示出来
- Lucene加中文分词paoding调研结果
- 海量数据库的查询优化及分页算法方案
- 跟日期有关的两条经典SQL语句
- 构建高性能网站的14条法则:把script放到页面的下端
- 实例演示在SQL中启用全文检索
- SQL SERVER实用经验技巧集 [三]
- 论有效的需求变更技术
- SQL SERVER实用经验技巧集 [二]
- 利用SQL移动硬盘文件