bbmonkey62笨笨猴

中文分词

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  2 随笔 :: 0 文章 :: 38 评论 :: 0 Trackbacks

ShuzhenAnalyzer-1.1.8与上一版本1.1.7在功能上没有任何区别,版本的升级是为了能够与lucene1.1.8一起使用。

对于搜索引擎而言,如果是提供一个类似于Google那样的web界面搜索的话,那对搜索结果进行高亮显示就很重要且必要了,不然将是非常不友好的,本篇文章就是介绍在lucene中应用HighLighter时的一些方面;文章分两部分,第一部分是介绍如何在lucene中应用Highlighter进行高亮显示而不影响到搜索速度。第二部分则是对一些高亮错误现象进行分析并给出解决方法,以及纠正对高亮错误存在的认识误区。总之,这篇文章就是希望能彻底解决在lucene中应用高亮显示所遇到的一切问题!另外淑珍分词器也发布了新的版本ShuzhenAnalyzer-1.1.6,也给出了一个淑珍分词器的演示地址


第一部分:在lucene中应用高亮显示而不影响到搜索的速度

淑珍分词器写好后,我做了些测试,这其中就包括对搜索结果进行命中的测试,当时我就发现了一个问题,那就是如果按照常规应用方法,比如按照目前市面上流行的介绍lucene的书籍中介绍的高亮显示方法,那搜索的速度就会降低,原因很简单,那是因为在进行高亮显示的时候,又进行了一次搜索,所以导致了搜索速度慢的问题,当时我对这个问题并没有深究,因为在平常中我用不着进行高亮处理,但前段时间有个朋友给我反馈1.1.4版本中存在的一个bug时,虽然这个bug与高亮无关,但却使我决定把1.1.4版本再完善一下,顺便解决这个高亮问题。

对于这个问题,我还是先搜索了一番,因为我想如果别人已经有很好的解决方法了,那我再自己费神去想就很没必要了,但搜索一番后,结果却是令自己不甚满意的,的确是有关于这方面的解决方法,但我觉得是并没有说得很清楚,首先这个思路应该是这样的:
1、在索引创建的时候,应当记录被索引的文字在被索引的内容中的确切位置,这个位置就是文字的开始位置和截止位置(比如“电脑”在内容“我们用电脑可以做很多事情”中的位置,我们可以得知起始是3,结束位置是5)。
2、然后在搜索得到结果的时候,应当将这些信息保存到内存中,以便高亮的时候不用再次遍历就可以很快地从内存中得到。
3、高亮的时候直接从内存中得到要被高亮文字的位置信息。

据说是lucene从1.4.3版本开始就支持在内存中记录搜索结果的位置信息了,依上处理为:

1、创建索引时:
Field f = new Field("title",title,Field.Store.YES, Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);

在Field类中,有
public static final TermVector WITH_POSITIONS_OFFSETS = new TermVector("WITH_POSITIONS_OFFSETS");
注释说明是:Store the term vector + Token position and offset information,就是做这个事的
常规的写法是没有Field.TermVector.WITH_POSITIONS_OFFSETS这个参数的
2、在HighlighterTest.java(你也可以新建一个类或改名,我是新建的一个类)中拷贝doStandardHighlights()的内容新建一个方法,将以下的
TokenStream tokenStream = analyzer.tokenStream(FIELD_NAME,new StringReader(text));
改为:
 1         TokenStream tokenStream = null;       
 2         if (reader==null){
 3             reader = IndexReader.open(indexPath);
 4         }
 5         //docNumber是文档ID,FIELD_NAME是索引字段
 6         TermPositionVector tpv = (TermPositionVector)reader.getTermFreqVector(docNumber,FIELD_NAME);
 7         //如果没有stop words去除还可以改成 TokenSources.getTokenStream(tpv,true); 进一步提速。
 8         if (tpv!=null){
 9             tokenStream=TokenSources.getTokenStream(tpv,true);
10         }

关于TermPositionVector类,不是必定全包含被搜索到的结果的位置和偏移位置,但至少会包含一项,这是对英文的直译,听来有点拗口,其实可以简单理解就是要得到结果的位置信息得找它!

好了,在lucene中应用高亮显示而不影响到搜索的速度介绍完了,但是,这样子高亮就一定正确吗?在接下来的第二部分中我会说明这还并不能百分百保证高亮正确,这也是我为什么考虑将两部分合在一起讲述的原因。

第二部分:影响高亮显示正确的因素

因素1:所使用的分词器不满足分词标准
现在的淑珍分词器最新版本是1.1.6,1.1.6与1.1.4版本相比较修正了两个Bug(之间还有1.1.5版本,修正了一个Bug),而这两个Bug都会导致在某种情况下高亮显示不正确,虽然这种情况并不罕见,甚至比Google的高亮显示Bug还不常见,但这毕竟是两个Bug。我在上一篇博文中提到过分词标准这个概念,我提到如果一个分词器不符合分词标准,那么在与高亮器一起使用时会导致高亮错误,这个提出也是基于我对分词器原理的一种较为深刻的理解而得出的吧,如果说上次提出的时候还只是很大可能推测的话,那么现在我却是敢肯定这点:那就是不满足分词标准的分词器必定会导致高亮错误。
在修正淑珍分词器这两个Bug的过程中,我发现原因都是我在写的过程中有两处地方没有符合分词标准的规范所导致的,而当我使之符合分词标准后,这两个Bug也没有了。
我在网上看到有些文章在碰到高亮错误的时候,没有想到是分词器的错误,而是去修改HighLighter等高亮器,我想这是错误的,这把一种原本正确的东西改错了,这也算是一种以讹传讹吧,我希望我的这篇文章能纠正这种错误的看法,不要让这种以讹传讹再继续下去了。

因素2:假设这个时候分词器也符合了分词标准的规范,但还有个情况我现在所发现会导致高亮错误,那就是所使用的高亮CSS样式,我碰到这种错误的时候,刚开始我以为是分词器还有其他地方没有符合分词标准的规范,但后来我确证百分百我的分词器没有问题了,而这个错误还是显示,这个时候我才意识到了是其他错误,以下是我搜索关键词“异界”,前后两次所使用的代码:
显示错误的:
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class=\"style7\">","</span>");

如图:

错误地方:界<
改后没问题的:
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b>","</b>");

(至于其他代码可以参看HighlighterTest.java)
如图:

当然,这个错误原因具体如何,我没有深究,有兴趣的同学可以去深入研究一下。。。



淑珍分词器ShuzhenAnalyzer-1.1.8下载地址见
http://www.blogjava.net/Files/bbmonkey62/ShuzhenAnalyzer-1.1.8-jdk1.6.0.rar

淑珍分词器ShuzhenAnalyzer-1.1.7下载地址见
For JDK1.6:
http://www.blogjava.net/Files/bbmonkey62/ShuzhenAnalyzer-1.1.7-jdk1.6.0.rar
For JDK1.5:
http://www.blogjava.net/Files/bbmonkey62/ShuzhenAnalyzer-1.1.7-jdk1.5.0.rar

关于分词器的详细介绍以及版本变更情况请参见:
http://www.shuzhen.net


posted on 2009-04-17 00:49 bbmonkey62笨笨猴 阅读(1852) 评论(3)  编辑  收藏

评论

# re: 解决在lucene中应用高亮显示所遇到的问题及ShuzhenAnalyzer-1.1.6发布 2009-04-17 09:41 mrzhu
麻烦问一下,用Lucene为文件建立索引的时候,如果我的文件是word类型的,而且文件中包含图片等非文本字符,Lucene只能对文本信息建立索引。查看详细的时候所有的图片都是乱码 这应该怎么解决啊 用POI读取java也只能抽文本  回复  更多评论
  

# re: 解决在lucene中应用高亮显示所遇到的问题及ShuzhenAnalyzer-1.1.6发布 2009-04-17 14:54 bbmonkey62笨笨猴
@mrzhu
在建立索引时,lucene是支持索引非文本数据的,我不知道你在索引的时候是怎么用的,但我建议你去看如下内容:
在org.apache.lucene.document.Field里的构造方法:
public Field(String name, byte[] value, Store store)
请留意第二个参数,在建立索引的时候允许非文本的字符,比如大文件类型转换为byte[]型索引起来,然后你取的时候再做相应的转换

我没做测试,你可以去测试下是否可行,我觉得是可以的。。。  回复  更多评论
  

# re: 解决在lucene中应用高亮显示所遇到的问题及ShuzhenAnalyzer-1.1.6发布 2009-04-17 17:38 bbmonkey62笨笨猴
请在2009-04-17下午5点35分以前下过1.1.6版本的朋友们再重新下一遍,由于我之前测试得不够严密,5点35分以前的1.1.6版本在对搜索词进行处理(segmentKeyExact(key)和segmentKeyFuzzy(key))时,当搜索词是某种组合的时候会导致比较严重的错误,其他功能没有发现问题,非常抱歉,敬请谅解  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: