Google

星期二, 六月 03, 2008

在pyLucene中使用中文分词器(在pyLucene中引用Jar包)

(刚刚解决的一个问题,在中文里面没有搜索到相关内容(英文里其实也没搜到...),发一篇在这里备人索引,关键字:pyLucene, JCC,
Lucene, Importing JAR)

在Lucene里面引用别人写好的中文分词器很简单,加个CLASSPATH就好。但是在pyLucene(JCC版)里,由于python所能够引用
到的Jar包都是用JCC这个编译器(姑且认为是个编译器吧)预先编译了python调用接口的。(反过来说,就是没有经JCC编译的Jar包是休想在
python里面直接访问的)

所以,在pyLucene中使用Jar包形式的中文分词器不得不重新编译。分隔线以下是OSFoundation某热心人关于如何修改Makefile
让Jar包可以和pyLucene打包到一起的回复。

-------------------------------------热心人回复的分隔
线-------------------------------------
Andi Vajda:
To access your class(es) by name from Python, you must have JCC
generate wrappers for it (them). This is what is done line 177 and on
in PyLucene's Makefile. The easiest way for you to add your own Java
classes to PyLucene is to create another jar file with your own
analyzer classes and code and add it to the JCC invocation there.

For example, the Makefile snippet in question currently says:

GENERATE=$(JCC) $(foreach jar,$(JARS),--jar $(jar)) \
--package java.lang java.lang.System \
java.lang.Runtime \
--package java.util \
java.text.SimpleDateFormat \
--package java.io java.io.StringReader \
java.io.InputStreamReader \
java.io.FileInputStream \
--exclude org.apache.lucene.queryParser.Token \
--exclude org.apache.lucene.queryParser.TokenMgrError \
--exclude
org.apache.lucene.queryParser.QueryParserTokenManager \
--exclude org.apache.lucene.queryParser.ParseException \
--python lucene \
--mapping org.apache.lucene.document.Document 'get:(Ljava/
lang/String;)Ljava/lang/String;' \
--mapping java.util.Properties 'getProperty:(Ljava/lang/
String;)Ljava/lang/String;' \
--sequence org.apache.lucene.search.Hits 'length:()I' 'doc:
(I)Lorg/apache/lucene/document/Document;' \
--version $(LUCENE_VER) \
--files $(NUM_FILES)

change the first line to say:

GENERATE=$(JCC) $(foreach jar,$(JARS),--jar $(jar)) --jar myjar.jar \
...

and rebuild PyLucene. That should be all you need to do. Your jar file
is going to be installed along with lucene's in the lucene egg and it
is going to be put on lucene.CLASSPATH which you use with
lucene.initVM().

Your classes can be declared in any Java package you want. Just make
sure that their names don't clash with other Lucene class names that
you also need to use as the class namespace is flattened in PyLucene.

For more information about JCC and its command line args see JCC's
README file at [1].

Andi..

[1] http://svn.osafoundation.org/pylucene/trunk/jcc/jcc/README
_______________________________________________
pylucene-dev mailing list
pylucene-...@osafoundation.org
http://lists.osafoundation.org/mailman/listinfo/pylucene-dev


http://groups.google.com.pe/group/python-cn/browse_thread/thread/0f085de0eab6f039

标签: , ,

Lucene倒排索引原理

Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:

0)设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.

1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”
e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成

经过上面处理后
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]

2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成
关键词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1

通 常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字 符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记 录的就是这种位置。

加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
关键词 文章号[出现频率] 出现位置
guangzhou 1[2] 3,6
he 2[1] 1
i 1[1] 4
live 1[2],2[1] 2,5,2
shanghai 2[1] 3
tom 1[1] 1

以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现 频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。

以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。

实 现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信 息。

Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。

为 了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例 如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值 的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382, 压缩后保存7(只用一个字节)。

下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。

http://www.cnitblog.com/donne/archive/2007/12/04/37331.html

标签:

Python下的Lucene,PyLucene

下一个项目准备用Python+Django来完成,先做些技术准备。数据库方面用Django已经 试验的差不多了,但是似乎性能很差。自己编译了Mysql,用虚拟机测试,生成1000个用户,1000篇文章用时80秒,这种并发性能恐怕没有办法让人 满意。(每篇文章需要单独生成Tag和文章与Tag的对应关系,涉及8次数据库操作。)花了一天时间试验InnoDB和MyIsam的区别,但是似乎没有 影响,开不开Transaction都一样。先不管它了,也许和我的机器硬件有关系,硬件的sync关不掉。看官方的说法,SlashDot用 Django可以实现每秒800条数据的插入速度。

网站肯定要用到全文检索,目前唯一的全文检索解决方案就是Lucene了,.Net上也有Lucene.Net可以选。搜索了一下,发现了PyLucene,这个Python上的Lucene实现。似乎是使用Python对Lucene进行了一次重新包装。

下 载了它的Windows版本,安装比较简单,直接把几个库文件复制到对应的Lib目录就行了。运行了一下Sample目录下的测试文件,先是用 IndexFiles和SearchFiles试了一下,SearchFiles是接收参数来搜索的,但是我没有办法输入中文,会出现错误提示。后来把要 搜索的词直接放到文件里面去,不报错了,但是搜索不出来。本以为PyLucene不支持中文,正在纳闷豆瓣的搜索是怎么做的,突然发现了一个好东西。

看 了一下sample目录下的LuceneInAction目录,里面居然有个ChineseTest文件。它调用的是另一个目录下的测试文件,测试一个汉 字的搜索,运行了一下,居然是成功的。再看了一下IndexFiles,里面读文件用的编码是英文编码,改成GB2312,OK,可以搜索到了。但是只能 搜索单字,不能按词搜索。只要输入两个字就出错。再比较一下Test文件,Query的生成方法不一样,TermQuery似乎是单元搜索,不支持词搜 索,换成了QueryParser,成功了。但是还有一个小问题,比如搜索“中华”,在文章里,在中和华中间随便加多少空格和回车都没有关系,照样可以搜 索到。但是加入其它字或者英文字母以后就搜索不到了。这个影响不大,毕竟人们常用的搜索都是自然词。

有了PyLucene这个好东西,心头一块大石头算是落地了。没想到,等到要在开发服务器的Linux上安装这个东西的时候,可费了功夫了。

官 方的下载包做的很奇怪,ubuntu, debian, gentoo都有对应的二进制包可用,但是Redhat就没有,只能用源码包编译,而它的编译方式又做的极其简陋,没有configure文件,只有 Makefile。按照说明,需要自己编辑Makefile,去掉你需要的注释行,修改参数,然后直接Make。但是里面有一个对DB的引用,检查了一 下,BerkeleyDB似乎在CentOS4里面没有,只好自己去官方网站下载了4.4.20的源码,先编译安装它。虽然最新版是4.5.20,但是怕 不兼容,所以还是用它配置文件里推荐的这个。编译这个东西也挺奇怪,不过还好,毕竟有官方文档一步步的说明,解压后需要进入build_unix目录,然 后调用../dist/configure来配置,然后make && make install。指定prefix失败。装完了这个东西,再改PyLucene的配置文件,根据生成的错误消息猜了好几次才终于可以编译了。最终需要改的 地方为:

1、取消Linux那一段的注释。

2、PREFIX_PYTHON是你的Python的目录。因为我的Python是自己编译安装的,所以这里需要改一下。

3、DB=这个我指向了BerkeleyDB的源码目录才通过编译的(还好没删)。

其 它的不用改。编译到一半报错,有一个libgcj.a文件找不到,到/usr/lib下找了一下没有这个文件,但是有个差不多的.so,于是做了个ln -s,居然就通过编译了。然后make install的时候又有问题,提示libgcc_s.so.1找不到,这个是Makefile里面的LIB_INSTALL参数指定的,我不知道它的意 义在哪里,最后我也没找到这个文件,但是直接进入Sample目录运行了一下测试文件,居然就成功了。真TMD。这就是Linux吗?

终于可以安心的研究Django了。似乎Ruby On Rails还没有支持中文全文检索的模块吧?

http://www.cnblogs.com/unfish/archive/2006/10/25/539956.html

标签: , ,

星期日, 七月 22, 2007

php + clucene extension的安装

CLuceneSF上面的一个对Lucene(一个用Java写的全文检索引擎工具包)的移植,做为Lucene的C++的重新实现,以带来更快的检索速度,但是一直还不stable.这里仅仅是尝试php+clucene扩展的安装,具体应用先不管.

安装环境:
Freebsd 6.0 + apache 2.2 + php 5.1.2

apache+php的安装就不说了,网上一抓一大把,注意clucene扩展必须在php5以上才能安装.

  • 首先安装clucene

1.下载clucene
直奔它的首页–clucene.sourceforge.net,下载clucene 0.9.10
2.编译clucene

tar xzvf clucene-0.9.10.tar.gz
cd clucene-0.9.10
./autogen.sh
./configure
make

这样clucene就安装好了,为了让其它程序可以调用clucene,这里把编译好的lib放到系统lib目录下

cp src/.libs/libclucene.* /usr/local/lib
cp src/CLucene.h /usr/local/include/
cp -r src/CLucene /usr/local/include/

  • 安装clucene php extension

1.下载clucene php extension
在pecl.php.net有下载,拖回来就是
http://pecl.php.net/package/clucene

2.编译clucene php extension

tar xzvf clucene-0.0.9.tgz
cd clucene-0.0.9
cp -r /usr/local/include/Clucene include/ #编译时要把clucene的include文件弄一份
cp -r /usr/local/include/Clucene.h include/
phpize
./configure
make

编译完成,这里会生成一个clucene.so,我们把它放在php的extension目录下(没有就建一个),然后修改php.ini

加入
extension=clucene.so

重启apache之后看phpinfo

php+clucene

至此安装就算完成了,demo嘛在examples目录下有一个,命令行调用方式(根据已有的index检索):
php clucene.php “Your query”

BTW:新出的zend framework也有lucene模块,但是功能还不完善,现在0.1.2好像只能建立索引,检索功能尚在开发中

作者: volcano 发表于3月 22, 2006 at 2:28 pm

版权信息: 可以任意转载, 转载时请务必以超链接形式标明文章原始出处作者信息及此声明

标签: , , ,

辽ICP备05003652号
流风洄雪听天籁,轻云蔽日看落花

Powered by Blogger