手把手教你作關鍵詞匹配項目(搜索引擎)---- 第十九天

客串:屌絲的坑人表單神器php

走過的那些事兒:數據庫那點事兒html

探討:探討負載均衡算法

面向對象的認識:面向對象的認識----新生的初識面向對象的番外----思想的夢遊篇(1)sql

 

起點:手把手教你作關鍵詞匹配項目(搜索引擎)---- 第一天數據庫

回顧:手把手教你作關鍵詞匹配項目(搜索引擎)---- 第十八天負載均衡

 

第十九天post

上回咱們一直提到字典的構建,以及寶貝屬性的特殊處理,提得太多,致使如今整個系統還不能徹底的運行起來。搜索引擎

小帥帥要多在這方面下功夫了。spa

就算上次咱們提到的用SQL語句裏面的對屬性LIKE,對黑名單NOT LIKE也沒法解決全部的問題,咱們只是把須要匹配的關鍵詞縮小了範圍。code

咱們拿一個實例來講明下:

有個寶貝是雪紡連衣裙,那麼雪紡連衣裙a 、新潮雪紡連衣裙a、韓版雪紡女裙a、高仿雪紡女裙、正品女裙等這些詞能用嗎?

小帥帥、於老大、小樂樂、小歡歡以及小哼哼一致認爲須要爲每一個關鍵詞跟寶貝屬性(字典)作匹配,當匹配度處於某個值,好比>=80%的時候可用。

小帥帥又納悶了,怎麼作到爲每一個關鍵詞跟寶貝屬性(字典)作匹配呢?

當時於老大就提到用關鍵詞拆分算法,這個算法其實很簡單,原理以下:

把關鍵詞按業務詞彙拆成詞組或者單詞,對每一個單詞或者詞組算出在整個關鍵詞所佔的比例,好比:雪紡連衣裙a 那麼會被拆分紅雪紡、連衣裙和a,那麼相應的比例爲33%、50%和17%。

而後再根據所拆成的詞組或者單詞同寶貝屬性(字典)作對比,那麼算出匹配成功的總比例來決定是否可用。好比寶貝是雪紡連衣裙,那麼雪紡連衣裙a,所獲得的匹配度爲33%+50%=83%。

 

當這個算法一講解完畢,小帥帥就迫不急待的寫了代碼,代碼以下:

<?php

class Splitter {

    /**
     * 獲取類目下分詞的詞組數據,按字符串長度比較排序
     * @param $cid
     * @return array
     */
    public static function getWordSegmentation($cid){

        $ret = array();
        $sql = "select word from category_linklist where cid='$cid'";
        $words = DB::makeArray($sql);
        foreach($words as $strWords){
            $words = explode(",",$strWords);

            foreach($words as $word){
               if(self::isPhrase($word)){
                    $ret[] = $word;
                }
            }
        }

        usort($ret,function($a,$b){
            return (strlen($a)<strlen($b))?1:-1;
        });

        return $ret;
    }

    /**
     * 檢測是否爲詞組
     * @param $word
     * @return bool
     */
    public static function isPhrase($word){
        if(preg_match('/^[\x{4E00}-\x{9FA5}]+$/u', $word) && strlen($word) <= 3){
            return false;
        }

        if(strlen($word)<=1){
            return false;
        }
        return true;
    }


    /**
     * 把關鍵詞拆分紅詞組或者單詞
     * @param $keyword
     * @param $cid
     * @return array
     */
    public static function split($keyword,$cid){

        $splitWords = array();
        $splitSegmentation = self::getWordSegmentation($cid);
        $remainKeyword = $keyword;

        foreach($splitSegmentation as $phrase){

            if(count(explode($phrase,$remainKeyword))>1){
                $splitWords[] = $phrase;
                $remainKeyword = str_replace($phrase,"::",$remainKeyword);
            }
        }

        $remainKeywords = explode("::",$remainKeyword);
        $splitWords = array_merge($splitWords,$remainKeywords);

        $keywordScores = array();
        foreach($splitWords as $splitWord){

            $keywordScore = new KeywordScore();
            $keywordScore->splitWord = $splitWord;
            $keywordScore->weight = self::calculateWeight($splitWord,$keyword);
            $keywordScores[] = $keywordScore;
        }

        return $keywordScores;

    }

    /**
     * @desc 計算UTF8字符串權重
     * @param string $splitWord
     * @param string $word
     * @return float
     */
    public static function calculateWeight($splitWord, $word)
    {
        return ROUND(strlen($splitWord) / strlen($word), 3);
    }

}


class KeywordScore {

    public $splitWord;
    public $weight;

}

小帥帥寫這個也是一點一點通過屢次重構而得來的結果,他不想讓於老大失望,因此一再精益求精。

小帥帥把代碼拿給於老大看的時候,於老大會有什麼反應呢,請看下回分解.

相關文章
相關標籤/搜索