返回列表 回复 发帖

[ZendFramework] [组件]Zend_Search_Lucene的,支持中文

[ZendFramework] [组件]Zend_Search_Lucene的,支持中文

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

首先按照hightman的方法给Zend Framework打个补丁,具体请看:
http://bbs.chinaunix.net/archiver/?tid-746635.html

然后自己实现分词方法,我的分词方法是按照hightman的php简易分词程序改写的,比他的还简易,当然正确率低。
代码写的时候因为赶时间,看上去比较dirty

<?php



Zend
::loadClass("Zend_Search_Lucene_Analysis_Analyzer_Common");

Zend::loadClass("Faq_Model_Dict");



class 
Faq_MySearch_MyAnalyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common

{

    
/** 成词标记 **/

    
const _WORD_ALONE_  0x4000000;

    
/** 词根标记 **/

    
const _WORD_PART_   0x8000000;

    
/**

     * 待分词的文字

     *

     * @var string

     */

    
protected $_strData;

    
/**

     * 句子的长度(字符数)

     *

     * @var int

     */

    
protected $_intLen;

    
/**

     * 词典

     *

     * @var Dict

     */

    
protected $_objDict;

    
/**

     * 字母 

     *

     * @var string

     */

    
protected $_strAlphaChars   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    
/**

     * 数字

     *

     * @var string

     */

    
protected $_strNumChars     "01234567890123456789";

    
/**

     * 标点

     *

     * @var string

     */

    
protected $_strSignChars    "~`!@#\$%^&*()_-+=|\\{}[]:\";'<>,.?/~!@#$%︿&*()_-+=|、{}[]:;“”‘’《》,。?/`……¥";

    
/**

     * 对一段文字分词,返回Token

     *

     * @param string $strData

     * @return array

     */

    
public function tokenize($strData){

        
$arrRet $this->scsw($strData);

        
//处理完毕,$arrRet即为分词结果

        
foreach($arrRet as $arrWord){

            
$objToken   = new Zend_Search_Lucene_Analysis_Token($arrWord[0],$arrWord[1],$arrWord[1]+strlen($arrWord[0]));

            
$arrToken[] = $this->normalize($objToken);

        }

        
//($arrToken);

        
return $arrToken;

    }

    
/**

     * 对一段文字分词,返回一个数组

     *

     * @param string $strData

     * @return array

     */

    
public function scsw($strData){

        
$this->_objDict = new Faq_Model_Dict();

        
$this->_intLen  mb_strlen($strData);

        
$this->_strData $strData;

        
$intLen $this->_intLen;

        
$intOffset 0;

        
$intSOffset 0;    //单字节位置

        
$strLastType    "space";  //当前状态为空白

        
$strWord    "";

        
$arrRet     = array();

        while(
$intOffset $intLen){

            
//取得一个字符

            
$strChar mb_substr($strData,$intOffset,1);

            
$intOffset++;

            if(
$this->_isAlpha($strChar)){

                
//是一个字母

                
if($strLastType!="alpha"&&$strWord!=""){

                    
//如果前一个字符不是字母不是空白,且词不为空,则记录这个词

                    
$arrRet[]   = array($strWord,$intSOffset);

                    
$intSOffset += strlen($strWord);

                    
$strWord    "";

                }

                
//然后继续读取

                
$strWord    .= $strChar;

                
$strLastType    "alpha";

                continue;

            }else if(
$this->_isNum($strChar)){

                
//是一个数字

                
if($strLastType!="num"&&$strWord!=""){

                    
//如果前一个字符不是数字不是空白,且词不为空,则记录这个词

                    
$arrRet[]   = array($strWord,$intSOffset);

                    
$intSOffset += strlen($strWord);

                    
$strWord    "";



                }

                
//然后继续读取

                
$strWord    .= $strChar;

                
$strLastType    "num";

                continue;

            }else if(
$this->_isSpace($strChar)){

                
//是一个空白

                
if($strLastType!="space"&&$strWord!=""){

                    
//如果前一个字符不是空白,且词不为空,则记录这个词

                    
$arrRet[]   = array($strWord,$intSOffset);

                    
$intSOffset += strlen($strWord);

                    
$strWord    "";

                }

                
//不读取空白

                
$strLastType    "space";

                
$intSOffset += strlen($strChar);

                continue;

            }elseif(
ord($strChar)>=176){

                
//其它字符

                
if($strLastType!="cword"&&$strWord!=""){

                    
//如果前一个字符不是汉字,且词不为空,则记录这个词

                    
$arrRet[]   = array($strWord,$intSOffset);

                    
$intSOffset += strlen($strWord);

                    
$strWord    "";

                }

                
$strLastType    "cword";

                
//继续读取

                
if($arrRow $this->_objDict->find($strWord.$strChar)){

                    
//是词

                    
$intFreqE   $arrRow->info;

                    if(
$intFreqE self::_WORD_PART_ ){

                        
//是词根

                        
$strWord .= $strChar;

                        continue;

                    }elseif (
$intFreqE self::_WORD_ALONE_){

                        
//是成词

                        
$arrRet[]   = array($strWord.$strChar,$intSOffset);

                        
$intSOffset += strlen($strWord.$strChar);

                        
$strWord    "";

                        continue;

                    }



                }

                
//不是词,记录旧词,开始一个新词

                
if($strWord!=""){

                    
$arrRet[]   = array($strWord,$intSOffset);

                    
$intSOffset += strlen($strWord);

                }

                
$strWord    $strChar;

                continue;

            }

        }

        if(
$strWord!=""){

            
$arrRet[]   = array($strWord,$intSOffset);

        }

        return 
$arrRet;

    }

    
/**

     * 判断是否是字母

     *

     * @param string $strChar

     * @return boolean

     */

    
protected function _isAlpha($strChar){

        
$intPos mb_strpos($this->_strAlphaChars$strChar);

        return (
$intPos !== false);

    }



    
/**

     * 判断是否为数字

     *

     * @param string $strChar

     * @return boolean

     */

    
protected function _isNum($strChar){

        
$intPos mb_strpos($this->_strNumChars$strChar);

        return (
$intPos !== false);

    }



    
/**

     * 判断是否是空白或标点

     *

     * @param string $strChar

     * @return boolean

     */

    
protected function _isSpace($strChar){

        
$intOrd ord($strChar);

        if (
$intOrd === 0x0d || $intOrd === 0x20 || $intOrd === 0x09){

            return 
true;

        }

        
$intPos mb_strpos($this->_strSignChars$strChar);

        return (
$intPos !== false);

    }

}

?>

复制代码
新建索引:
function addIndex($content,$id,$cat_id){

                
$objLucene = new Zend_Search_Lucene(INDEX_PATH);

                
$objDoc = new Zend_Search_Lucene_Document();

                
$objDoc->addField(Zend_Search_Lucene_Field::UnStored('contents'$content));

                
$objDoc->addField(Zend_Search_Lucene_Field::Text('faqid'$id));

                
$objDoc->addField(Zend_Search_Lucene_Field::Text('catid'$cat_id));

                
$objLucene->addDocument($objDoc);

                
$objLucene->commit();

                return 
true;

        }


复制代码
检索的时候:
/** 进行分词 **/

                
$arrRet $objAnalyzer->scsw($res['question']);

                
/** 开始检索 **/

                
$query = new Zend_Search_Lucene_Search_Query_MultiTerm();

                foreach (
$arrRet as $arrWord) {

                        
$query->addTerm(new Zend_Search_lucene_Index_term($arrWord[0]));

                }

                
$query->addTerm(new Zend_Search_lucene_Index_term($res['cat_id'],"catid"));

                
$index = new Zend_Search_Lucene(INDEX_PATH);

                
$hits $index->find($query);

复制代码
修改成高亮显示..好读一些
不错,支持!
楼上的老大,有没有实际的例子给个url看看 效果

顶一下

好东西
其实我就是改变社会风气,风靡万千少女,
刺激PHP市场,提高年轻人内涵,
玉树临风,风度翩翩的PHPer

Zend::loadClass("Faq_Model_Dict"); 词典谁提供一下啊

系统中好象没有这个文件
返回列表