• 手把手教你做关键词匹配项目(搜索引擎)---- 第十九天


    客串:屌丝的坑人表单神器

    走过的那些事儿:数据库那点事儿

    探讨:探讨负载均衡

    面向对象的认识:面向对象的认识----新生的初识面向对象的番外----思想的梦游篇(1)

    起点:手把手教你做关键词匹配项目(搜索引擎)---- 第一天

    回顾:手把手教你做关键词匹配项目(搜索引擎)---- 第十八天

    第十九天

    上回我们一直提到字典的构建,以及宝贝属性的特殊处理,提得太多,导致现在整个系统还不能完全的运行起来。

    小帅帅要多在这方面下功夫了。

    就算上次我们提到的用SQL语句里面的对属性LIKE,对黑名单NOT LIKE也无法解决所有的问题,我们只是把需要匹配的关键词缩小了范围。

    我们拿一个实例来说明下:

    有个宝贝是雪纺连衣裙,那么雪纺连衣裙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;
    
    }

    小帅帅写这个也是一点一点经过多次重构而得来的结果,他不想让于老大失望,所以一再精益求精。

    小帅帅把代码拿给于老大看的时候,于老大会有什么反应呢,请看下回分解.

  • 相关阅读:
    4/19学习总结
    人月神话读后感8
    4/18学习总结:PullToRefresh
    构建之法阅读笔记03
    构建之法阅读笔记02
    个人总结
    大二下学期课程总结
    学习进度16
    学习进度15
    课堂测试-找英语单词最长链
  • 原文地址:https://www.cnblogs.com/oshine/p/3949090.html
Copyright © 2020-2023  润新知