目录
手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天
首页 php教程 php手册 手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天

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

Jun 13, 2016 am 09:25 AM
- 关键词 匹配 手把手 搜索引擎 教你 项目

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

客串:屌丝的坑人表单神器、数据库那点事儿

面向对象升华:面向对象的认识----新生的初识、面向对象的番外----思想的梦游篇(1)、面向对象的认识---如何找出类

负载均衡:负载均衡----概念认识篇、负载均衡----实现配置篇(Nginx)

吐槽:有人反馈了这样的一个信息,说该文章越到最后越难看懂,跟不上节奏,也有的人说小帅帅的能力怎么飙的那么快,是不是我比较蠢。也有的直接看文字,不看代码,代码太难懂了。

其实我这几天也一直在思考这个问题,所以没办法就去开展了一些面向对象的课程,希望对那些跟不上的有些帮助。其实说真的,读者不反馈的话,我只好按照我认为的小帅帅去开展课程了。

 

第二十天

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

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

话说小帅帅为了解决那个分词算法写出了初版,他拿给于老大看的时候,被要求重写了。

原因有以下几点:

    1. 如何测试,测试数据呢?

    2. Splitter是不是做了太多事情?

    3. 连衣裙xxl裙连衣裙这种 有重复词组怎么办?

小帅帅拿着这些问题,开始重构。

首先他发现了这点,中文、英文和中英文的判断,以及长度的计算,他把这个写成了类:

<?<span>php

</span><span>class</span><span> UTF8 {

    </span><span>/*</span><span>*
     * 检测是否utf8
     * @param $char
     * @return bool
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> is(<span>$char</span><span>){
        </span><span>return</span> (<span>preg_match</span>("/^([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){1}/",<span>$char</span>) ||
            <span>preg_match</span>("/([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){1}$/",<span>$char</span>) ||
            <span>preg_match</span>("/([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){2,}/",<span>$char</span><span>));
    }

    </span><span>/*</span><span>*
     * 计算utf8字的个数
     * @param $char
     * @return float|int
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> length(<span>$char</span><span>) {

        </span><span>if</span>(self::is(<span>$char</span><span>))
            </span><span>return</span> <span>ceil</span>(<span>strlen</span>(<span>$char</span>)/3<span>);
        </span><span>return</span> <span>strlen</span>(<span>$char</span><span>);
    }

    </span><span>/*</span><span>*
     * 检测是否为词组
     * @param $word
     * @return bool
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> isPhrase(<span>$word</span><span>){

        </span><span>if</span>(self::length(<span>$word</span>)<=1<span>)
            </span><span>return</span> <span>false</span><span>;
        </span><span>return</span> <span>true</span><span>;
    }

}</span>
登录后复制

小帅帅又考虑到词典的来源有可能来自多个地方,比如我给的测试数据,这样不就是可以解决于老大说到无法测试的问题了,小帅帅把词典的来源抽成了个类,类如下:

<?<span>php

</span><span>class</span><span> DBSegmentation {

    </span><span>public</span> <span>$cid</span><span>;

    </span><span>/*</span><span>*
     * 获取类目下分词的词组数据
     * @return array
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> transferDictionary(){
        </span><span>$ret</span> = <span>array</span><span>();
        </span><span>$sql</span> = "select word from category_linklist where cid='<span>$this</span>->cid'"<span>;
        </span><span>$words</span> = DB::makeArray(<span>$sql</span><span>);
        </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$strWords</span><span>){
            </span><span>$words</span> = <span>explode</span>(",",<span>$strWords</span><span>);

            </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$word</span><span>){
                </span><span>if</span>(UTF8::isPhrase(<span>$word</span><span>)){
                    </span><span>$ret</span>[] = <span>$word</span><span>;
                }
            }
        }
        </span><span>return</span> <span>$ret</span><span>;
    }
} 

</span><span>class</span><span> TestSegmentation {
    
    </span><span>public</span> <span>function</span><span> transferDictionary(){
        </span><span>$words</span> = <span>array</span><span>(
            </span>"连衣裙,连衣",
            "XXL,xxl,加大,加大码",
            "X码,中码",
            "外套,衣,衣服,外衣,上衣",
            "女款,女士,女生,女性"<span>
        );

        </span><span>$ret</span> = <span>array</span><span>();
        </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$strWords</span><span>){
            </span><span>$words</span> = <span>explode</span>(",",<span>$strWords</span><span>);

            </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$word</span><span>){
                </span><span>if</span>(UTF8::isPhrase(<span>$word</span><span>)){
                    </span><span>$ret</span>[] = <span>$word</span><span>;
                }
            }
        }
        </span><span>return</span> <span>$ret</span><span>;

    }
}</span>
登录后复制

那么Splitter 就专心分词把,代码如下:

<span>class</span><span> Splitter {

    </span><span>public</span> <span>$keyword</span><span>;
    </span><span>private</span> <span>$dictionary</span> = <span>array</span><span>();

    </span><span>public</span> <span>function</span> setDictionary(<span>$dictionary</span> = <span>array</span><span>()){

        </span><span>usort</span>(<span>$dictionary</span>,<span>function</span>(<span>$a</span>,<span>$b</span><span>){
            </span><span>return</span> (UTF8::length(<span>$a</span>)>UTF8::length(<span>$b</span>))?1:-1<span>;
        });

        </span><span>$this</span>->dictionary = <span>$dictionary</span><span>;
    }

    </span><span>public</span> <span>function</span><span> getDictionary(){
        </span><span>return</span> <span>$this</span>-><span>dictionary;
    }

    </span><span>/*</span><span>*
     * 把关键词拆分成词组或者单词
     * @return KeywordEntity $keywordEntity
     </span><span>*/</span>
    <span>public</span> <span>function</span> <span>split</span><span>(){

        </span><span>$remainKeyword</span> = <span>$this</span>-><span>keyword;

        </span><span>$keywordEntity</span> = <span>new</span> KeywordEntity(<span>$this</span>-><span>keyword);

        </span><span>foreach</span>(<span>$this</span>->dictionary <span>as</span> <span>$phrase</span><span>){

            </span><span>$matchTimes</span> = <span>preg_match_all</span>("/<span>$phrase</span>/",<span>$remainKeyword</span>,<span>$matches</span><span>);
            </span><span>if</span>(<span>$matchTimes</span>>0<span>){
                </span><span>$keywordEntity</span>->addElement(<span>$phrase</span>,<span>$matchTimes</span><span>);

                </span><span>$remainKeyword</span> = <span>str_replace</span>(<span>$phrase</span>,"::",<span>$remainKeyword</span><span>);
            }
        }

        </span><span>$remainKeywords</span> = <span>explode</span>("::",<span>$remainKeyword</span><span>);
        </span><span>foreach</span>(<span>$remainKeywords</span> <span>as</span> <span>$splitWord</span><span>){

            </span><span>if</span>(!<span>empty</span>(<span>$splitWord</span><span>)){
                </span><span>$keywordEntity</span>->addElement(<span>$splitWord</span><span>);
            }
        }

        </span><span>return</span> <span>$keywordEntity</span><span>;

    }

}


</span><span>class</span><span> KeywordEntity {

    </span><span>public</span> <span>$keyword</span><span>;
    </span><span>public</span> <span>$elements</span> = <span>array</span><span>();

    </span><span>public</span> <span>function</span> __construct(<span>$keyword</span><span>){
        </span><span>$this</span>->keyword = <span>$keyword</span><span>;
    }

    </span><span>public</span> <span>function</span> addElement(<span>$word</span>,<span>$times</span>=1<span>){

        </span><span>if</span>(<span>isset</span>(<span>$this</span>->elements[<span>$word</span><span>])){
            </span><span>$this</span>->elements[<span>$word</span>]->times += <span>$times</span><span>;
        }</span><span>else</span>
            <span>$this</span>->elements[] = <span>new</span> KeywordElement(<span>$word</span>,<span>$times</span><span>);
    }

    </span><span>/*</span><span>*
     * @desc 计算UTF8字符串权重
     * @param string $word
     * @return float
     </span><span>*/</span>
    <span>public</span> <span>function</span> calculateWeight(<span>$word</span><span>)
    {
        </span><span>$element</span> = <span>$this</span>->elements[<span>$word</span><span>];
        </span><span>return</span> <span>ROUND</span>(<span>strlen</span>(<span>$element</span>->word)*<span>$element</span>->times / <span>strlen</span>(<span>$this</span>->keyword), 3<span>);
    }
}


</span><span>class</span><span> KeywordElement {
    </span><span>public</span> <span>$word</span><span>;
    </span><span>public</span> <span>$times</span><span>;

    </span><span>public</span> <span>function</span> __construct(<span>$word</span>,<span>$times</span><span>){
        </span><span>$this</span>->word = <span>$word</span><span>;
        </span><span>$this</span>->times = <span>$times</span><span>;
    }
}</span>
登录后复制

他把算权重的也丢给了一个类专门去处理。

小帅帅写完之后,也顺手写了测试实例:

<?<span>php

</span><span>$segmentation</span> = <span>new</span><span> TestSegmentation();

</span><span>$splitter</span> = <span>new</span><span> Splitter();
</span><span>$splitter</span>->setDictionary(<span>$segmentation</span>-><span>transferDictionary());
</span><span>$splitter</span>->keyword = "连衣裙xxl裙连衣裙"<span>;
</span><span>$keywordEntity</span> = <span>$splitter</span>-><span>split</span><span>();

</span><span>var_dump</span>(<span>$keywordEntity</span>);
登录后复制

 

这样就算你的算法怎么改,它也能从容面对了。

 

小帅帅理解了这个,当你觉得类做的事情太多的时候,可以考虑下单一职责原则。

 

单一职责原则:一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。【来自百度百科】

 

当于老大提到是不是有其他分词算法的时候,我们能不能拿来用,小帅帅很高兴,因为现在它的代码是多么美好。

小帅帅如何玩转第三方分词扩展,请继续关注下回分解:手把手教你做关键词匹配项目(搜索引擎)---- 第二十一天

 

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

小米 14 Ultra怎么调整光圈? 小米 14 Ultra怎么调整光圈? Mar 19, 2024 am 09:01 AM

光圈大小的调整对于拍照效果有着至关重要的影响,小米14Ultra在相机光圈调节方面提供了前所未有的灵活性。为了让大家都能顺利调节光圈,实现光圈大小的自由调节,小编在这里为大家带来了小米14Ultra怎么设置光圈的详细教程。小米14Ultra怎么调整光圈?启动相机,切换至“专业模式”,选择主摄-W镜头。点击光圈,打开光圈转盘,A为自动,按需选择f/1.9或f/4.0。

AI攻克费马大定理?数学家放弃5年职业生涯,将100页证明变代码 AI攻克费马大定理?数学家放弃5年职业生涯,将100页证明变代码 Apr 09, 2024 pm 03:20 PM

费马大定理,即将被AI攻克?而且整件事最意味深长的地方在于,AI即将解决的费马大定理,正是为了证明AI无用。曾经,数学属于纯粹的人类智力王国;如今,这片疆土正被先进的算法所破译,所践踏。图片费马大定理,是一个「臭名昭著」的谜题,在几个世纪以来,一直困扰着数学家们。它在1993年被证明,而现在,数学家们有一个伟大计划:用计算机把证明过程重现。他们希望在这个版本的证明中,如果有任何逻辑上的错误,都可由计算机检查出来。项目地址:https://github.com/riccardobrasca/flt

Cheat Engine怎么设置中文?ce修改器设置中文的方法 Cheat Engine怎么设置中文?ce修改器设置中文的方法 Mar 18, 2024 pm 01:20 PM

Ce修改器(CheatEngine)是一款专用于对游戏内存进行修改和编辑的游戏修改工具,那么在CheatEngine中怎么设置中文呢?接下来小编为大伙讲述ce修改器设置中文的方法内容,希望可以帮助到有需要的朋友。在我们下载的新软件中,若发现它不是中文界面,可能会让人感到困惑。尽管这款软件不是由中国开发的,但我们仍有方法将其转换为中文版本。只需简单地应用中文补丁,就能解决这个问题。在下载并安装了CheatEngine(ce修改器)软件后,打开安装位置,找到名为languages的文件夹,如下图所示

荣耀 90 GT怎么更新荣耀MagicOS 8.0? 荣耀 90 GT怎么更新荣耀MagicOS 8.0? Mar 18, 2024 pm 06:46 PM

荣耀90GT是一款性价比很高的智能手机,拥有出色的性能和出色的用户体验。然而,有时候我们可能会遇到一些问题,比如荣耀90GT怎么更新荣耀MagicOS8.0呢?这个步骤因为不同的手机不同的机型可能会有些区别,那么,让我们一起来探讨一下,如何正确地升级系统吧。荣耀90GT怎么更新荣耀MagicOS8.0?2月28日消息,荣耀今天为旗下90GT/100/100Pro三款手机推送MagicOS8.0公测更新,包版本号为8.0.0.106(C00E106R3P1)1.确保您的荣耀90GT的电池电量充足,

教你使用 iOS 17.4「失窃设备保护」新进阶功能 教你使用 iOS 17.4「失窃设备保护」新进阶功能 Mar 10, 2024 pm 04:34 PM

Apple在周二推出了iOS17.4更新,为iPhone带来了一系列新功能和修复。这次更新包括了全新的表情符号,同时欧盟用户也能够下载其他应用商店。此外,更新还加强了对iPhone安全性的控制,引入了更多的「失窃设备保护」设置选项,为用户提供更多选择和保障。"iOS17.3首次引入了“失窃设备保护”功能,为用户的敏感资料增加了额外的安全保障。当用户不在家等熟悉地点时,该功能要求用户首次输入生物特征信息,并在一小时后再次输入信息才能访问和更改某些数据,如修改AppleID密码或关闭失窃设备保护功能

Planet Mojo:从自走棋游戏Mojo Melee建起Web3游戏元宇宙 Planet Mojo:从自走棋游戏Mojo Melee建起Web3游戏元宇宙 Mar 14, 2024 pm 05:55 PM

成立于上个加密周期的热门元宇宙游戏项目们正在加速扩张。3月4日,Web3游戏元宇宙平台PlanetMojo宣布了其游戏生态的多个重要动态,包括预告即将推出跑酷游戏GoGoMojo、旗舰自走棋游戏MojoMelee推出新赛季“战之道”,以及为庆祝新赛季与MagicEden合作推出的首个ETH系列“WarBannerNFT”。另外,PlanetMojo还透露,他们计划在今年晚些时候推出MojoMelee的Android和iOS移动版本。这个项目在2021年底启动,经过在熊市中近两年的努力建设,即将在

DaVinci Resolve Studio 已支持AMD显卡的AV1硬件编码 DaVinci Resolve Studio 已支持AMD显卡的AV1硬件编码 Mar 06, 2024 pm 10:04 PM

最近新消息,lackMagic目前推出了达芬奇DaVinciResolveStudio视频编辑软件的18.5PublicBeta2公测版更新,为AMDRadeon显卡带来了AV1编码支持。更新到最新版本后,AMD显卡用户将能够在DaVinciResolveStudio中利用硬件加速来进行AV1编码。尽管官方并未具体指明支持的架构或型号,但预计所有的AMD显卡用户都可以尝试这一功能。2018年,AOMedia发布了全新的视频编码标准AV1(AOMediaVideoCodec1.0)。AV1是由多家

Cheat Engine如何设置中文?Cheat Engine设置中文方法 Cheat Engine如何设置中文?Cheat Engine设置中文方法 Mar 13, 2024 pm 04:49 PM

  CheatEngine是一款游戏编辑器,能够对游戏的内存进行编辑修改。但是它的默认语言是非中文的,对于很多小伙伴来说比较不方便,那么CheatEngine怎么设置中文呢?今天小编就给大家详细介绍一下CheatEngine设置中文的方法,希望可以帮助到你。  设置方法一  1、双击打开软件,点击左上角的“edit”。  2、接着点击下方选项列表中的“settings”。  3、在打开的窗口界面中,点击左侧栏中的“languages”

See all articles