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

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

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

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

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

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

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

第二十天

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

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

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

原因有以下几点:

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

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

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

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

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

phpclassUTF8 {/**

* 检测是否utf8

* @param $char

* @return bool*/

public static function is($char){return (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$char) ||

preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$char) ||

preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$char));

}/**

* 计算utf8字的个数

* @param $char

* @return float|int*/

public static function length($char) {if(self::is($char))return ceil(strlen($char)/3);return strlen($char);

}/**

* 检测是否为词组

* @param $word

* @return bool*/

public static function isPhrase($word){if(self::length($word)<=1)return false;return true;

}

}

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

phpclassDBSegmentation {public $cid;/**

* 获取类目下分词的词组数据

* @return array*/

public functiontransferDictionary(){$ret = array();$sql = "select word from category_linklist where cid='$this->cid'";$words = DB::makeArray($sql);foreach($words as $strWords){$words = explode(",",$strWords);foreach($words as $word){if(UTF8::isPhrase($word)){$ret[] = $word;

}

}

}return $ret;

}

}classTestSegmentation {public functiontransferDictionary(){$words = array("连衣裙,连衣",

"XXL,xxl,加大,加大码",

"X码,中码",

"外套,衣,衣服,外衣,上衣",

"女款,女士,女生,女性");$ret = array();foreach($words as $strWords){$words = explode(",",$strWords);foreach($words as $word){if(UTF8::isPhrase($word)){$ret[] = $word;

}

}

}return $ret;

}

}

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

classSplitter {public $keyword;private $dictionary = array();public function setDictionary($dictionary = array()){usort($dictionary,function($a,$b){return (UTF8::length($a)>UTF8::length($b))?1:-1;

});$this->dictionary = $dictionary;

}public functiongetDictionary(){return $this->dictionary;

}/**

* 把关键词拆分成词组或者单词

* @return KeywordEntity $keywordEntity*/

public function split(){$remainKeyword = $this->keyword;$keywordEntity = new KeywordEntity($this->keyword);foreach($this->dictionary as $phrase){$matchTimes = preg_match_all("/$phrase/",$remainKeyword,$matches);if($matchTimes>0){$keywordEntity->addElement($phrase,$matchTimes);$remainKeyword = str_replace($phrase,"::",$remainKeyword);

}

}$remainKeywords = explode("::",$remainKeyword);foreach($remainKeywords as $splitWord){if(!empty($splitWord)){$keywordEntity->addElement($splitWord);

}

}return $keywordEntity;

}

}classKeywordEntity {public $keyword;public $elements = array();public function __construct($keyword){$this->keyword = $keyword;

}public function addElement($word,$times=1){if(isset($this->elements[$word])){$this->elements[$word]->times += $times;

}else

$this->elements[] = new KeywordElement($word,$times);

}/**

* @desc 计算UTF8字符串权重

* @param string $word

* @return float*/

public function calculateWeight($word)

{$element = $this->elements[$word];return ROUND(strlen($element->word)*$element->times / strlen($this->keyword), 3);

}

}classKeywordElement {public $word;public $times;public function __construct($word,$times){$this->word = $word;$this->times = $times;

}

}

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

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

php$segmentation = newTestSegmentation();$splitter = newSplitter();$splitter->setDictionary($segmentation->transferDictionary());$splitter->keyword = "连衣裙xxl裙连衣裙";$keywordEntity = $splitter->split();var_dump($keywordEntity);

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

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

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

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

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

http://www.bkjia.com/PHPjc/873919.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/873919.htmlTechArticle手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天 客串:屌丝的坑人表单神器、数据库那点事儿 面向对象升华:面...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值