首页 | PHP资讯 | 技术专栏 | 资源共享 | PHP培训 | PHP职场 | 图书 | PHP ON WIN | PHP圈子 | PHPer学习大本营
返回列表 回复 发帖

[组件]Zend Framework的lucene全文检索初探

[组件]Zend Framework的lucene全文检索初探

本帖最后由 七月十五 于 2009-5-16 15:14 编辑

Author:feifengxlq<feifengxlq@hotmail.com> http://xlq521.blog.sohu.com
Time: 2006-7-6   
   最近一直研究lucene和nutch,但很遗憾都是JAVA的,一直想自己转写成PHP的。最近发现Zend Framework里面含有了lucene的全站检索功能。下午研究了一下,特写此文,希望对大家能有所帮助。
   
   前提:1、熟悉lucene检索的基本原理。不懂的推荐看一下<lucene in action>
         2、会配置使用Zend Framework!
  
   现在,让我们进行简单的一个构建索引(index)和查询过程(search)。

   首先,我们构建index。
   
indexer.php
<?php
require_once 'Zend/Search/lucene.php';

// Setting the second argument to TRUE creates a new index
$index = new Zend_Search_Lucene('my-index', true);

$doc = new Zend_Search_Lucene_Document();

// Store document URL to identify it in search result.
$doc->addField(Zend_Search_Lucene_Field::Text('url', 'http://www.eyuwo.com'));

// Index document content
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'this is just a test of Zend_Search_lucene'));

// Add document to the index.
$index->addDocument($doc);

// Write changes to the index.
$index->commit();
echo 'indexer one file!';
?>
   
运行后,你如果发现目录下有个my-index文件夹,里面有三个文件,说明你index成功!

  第二步,搜索。
  search.php

<?php
require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('my-index');//构建检索器,my-index为index目录

$query='test';//查询的关键字

$hits = $index->find($query);//得到查询的结果

foreach ($hits as $hit) {
    echo 'Score:'.$hit->score.'<br>';
    echo 'Url:'.$hit->url.'<br><hr>';
}
?>


代码里面有详细的说明了。
  如果你得到一个非空的array,说明你检索成功,可以开始深入学习了。

  PS:Zend_Search_Lucene我还在继续学习中,初看了下,中文分词方面可能要自己写分词器。虽然目前还不是很完善,但对于我们phper来说,的确是个好东西。

[ 本帖最后由 feifengxlq 于 2006-7-6 17:01 编辑 ]
PHP面对对象
征友情链接

好文..这个对搜索提高性能非常有用..中文分词方面只能自己来..用词库的方式分词..不然不能完美的解决中文搜索的问题.比如繁体和简体的转义等等..

lucene自带的中文分词方式是二分法..能解决一部分问题..但是极其有限..

比如:我在发帖,二分法是如下分词的:我在,在发,发帖.根据这几个作为搜索的最基本元素来搜索.

[ 本帖最后由 mikale 于 2006-7-6 18:33 编辑 ]

TOP

现在的lucene和nutch对中文支持都不错啦。不过都是java的,不爽
PHP面对对象
征友情链接

TOP

强顶下,期待两位的后继成果:)
Stay Hungry. Stay Foolish.

TOP

现在lucene的中文分词不是简单的二分法啦,有更新的了,你可以先2.0版本看看~呵呵

下午又研究了下zend Framework的lucene,发现它再分词方面也处理的太简单了。目前是只支持英文分词,而且就是简单的space(空格)分词。
它的分词算法的关键就是
[php]
$data='this is a test';
$position = 0;
        while ($position < strlen($data)) {
            // skip white space
            while ($position < strlen($data) && !ctype_alpha( $data{$position} )) {
                $position++;
            }

            $termStartPosition = $position;

            // read token
            while ($position < strlen($data) && ctype_alpha( $data{$position} )) {
                $position++;
            }

            // Empty token, end of stream.
            if ($position == $termStartPosition) {
                break;
            }

            /*$token = new Zend_Search_Lucene_Analysis_Token(substr($data,
                                             $termStartPosition,
                                             $position-$termStartPosition),
                                      $termStartPosition,
                                      $position);
            $tokenStream[] = $this->normalize($token);*/
            echo substr($data,$termStartPosition, $position-$termStartPosition).' '.$termStartPosition.' '.$position.'<br>';
        }
[/php]

我是取出它其中分词的关键,并稍微修改了下。你可以看出它的分词算法是如何的简单
PHP面对对象
征友情链接

TOP

原帖由 feifengxlq 于 2006-7-7 18:58 发表
现在lucene的中文分词不是简单的二分法啦,有更新的了,你可以先2.0版本看看~呵呵

下午又研究了下zend Framework的lucene,发现它再分词方面也处理的太简单了。目前是只支持英文分词,而且就是简单的space(空 ...


英文分词的话..这样就满足了..你试想一下英文书写规则..不过google这种分词有纠正拼写错误的..那就是另外一套算法了.

TOP

原帖由 mikale 于 2006-7-7 21:04 发表


英文分词的话..这样就满足了..你试想一下英文书写规则..不过google这种分词有纠正拼写错误的..那就是另外一套算法了.


不止这样的,分词前期还要做一些过滤处理的。比如,去掉一些非关键字、大小写转化等等~

仅仅WhitespaceAnalyzer对英文分词来说是远远不够的,对中文根本就行不通的。
PHP面对对象
征友情链接

TOP

网上找到的一个中文二元分词
[php]
<?
//Monkey's 二元分词
function sp_str($str) {
//所有汉字后添加ASCII的0字符,此法是为了排除特殊中文拆分错误的问题
$str=preg_replace("/[\x80-\xff]{2}/","\\0".chr(0x00),$str);
//拆分的分割符
$search = array(",", "/", "\\", ".", ";", ":", "\"", "!", "~", "`", "^", "(", ")", "?", "-", "\t", "\n", "'", "<", ">", "\r", "\r\n", "$", "&", "%", "#", "@", "+", "=", "{", "}", "[", "]", ":", ")", "(", ".", "。", ",", "!", ";", "“", "”", "‘", "’", "[", "]", "、", "—", " ", "《", "》", "-", "…", "【", "】",);
//替换所有的分割符为空格
$str = str_replace($search,' ',$str);
//用正则匹配半角单个字符或者全角单个字符,存入数组$ar
   preg_match_all("/[\x80-\xff]?./",$str,$ar);$ar=$ar[0];
   //去掉$ar中ASCII为0字符的项目
   for ($i=0;$i<count($ar);$i++) if ($ar[$i]!=chr(0x00)) $ar_new[]=$ar[$i];
   $ar=$ar_new;unset($ar_new);$oldsw=0;
/*
$ar = Array
(
     [0] => M
     [1] => o
     [2] => n
     [3] => k
     [4] => e
     [5] => y
     [6] =>
     [7] => s
     [8] =>
     [9] => 二
     [10] => 元
     [11] => 分
     [12] => 词
)
*/
//把连续的半角存成一个数组下标,或者全角的每2个字符存成一个数组的下标
   for ($ar_str='',$i=0;$i<count($ar);$i++) {
    $sw=strlen($ar[$i]);
    if ($i>0 and $sw!=$oldsw) $ar_str.=" ";
     if ($sw==1) $ar_str.=$ar[$i];
    else
     if (strlen($ar[$i+1])==2) $ar_str.=$ar[$i].$ar[$i+1].' ';
     elseif ($oldsw==1 or $oldsw==0) $ar_str.=$ar[$i];
    $oldsw=$sw;
   }
   //去掉连续的空格
   $ar_str=trim(preg_replace("# {1,}#i"," ",$ar_str));//$ar_str = "Monkey s 二元 元分 分词"
   //返回拆分后的结果
   return explode(' ',$ar_str);
}

print_r(sp_str("Monkey's 二元分词"));

/*
Array
(
    [0] => Monkey
    [1] => s
    [2] => 二元
    [3] => 元分
    [4] => 分词
)
*/
[/php]
PHP面对对象
征友情链接

TOP

俺最近做了个视频搜索的,包括数据采集。。。有空给大家PP
PHP面对对象
征友情链接

TOP

一直在关注这个。有一点疑问就是:使用lucene用不用安装java的那个东东?

TOP

返回列表