1,需求
像我们如果有一批新闻资讯,要匹配这批新闻对应的关联到相关公司里面。
2,解决思路
方法1:
①储存公司数组
②遍历公司数据,去查新闻标题或者内容是否存在该公司名
③完成匹配
优点:代码逻辑简单
缺点:耗时,不确定性强。公司数据越则越耗时。
方法2:
①引入分词
②公司名加入字库
③标题或者内容分词,是我们指定的公司名字库
④匹配对应公司名
⑤匹配完成
优点:快速,确定性强,匹配一条时间相对固定。
缺点:代码逻辑相对复杂
下面主要是阐述方法2的代码逻辑
3,相关代码
①引入分词
GitHub - lizhichao/VicWord: 一个纯php分词
安装方法和使用方法可以查看上面网址
composer安装:composer require lizhichao/word
②公司名加入字库
这边做了两个处理,一个是把入了字库的公司名,存在缓存中,防止重复入库。另一个是加了自己特殊的词性“company_name”是为了后面分词可以定位到这个关键词。
//添加字库
static public function add_company_word($str){
$str=trim($str);
$words=Cache::get("company_word");
if(empty($words)){
$words=[];
}
//防止重复添加
if(in_array($str,$words)){
return;
}
array_push($words,$str);
Cache::set("company_word",$words);
$dict = new VicDict();
//添加词语词库 add(词语,词性) 不分语言,可以是utf-8编码的任何字符
$dict->add($str,"company_name");
//保存词库
$dict->save();
}
③标题或者内容分词,是我们指定的公司名字库
例如我们使用“港股快报 | 宋都服务收涨21.88% 收盘价0.117港元/股”分词效果如下:
便会匹配到我们字库关键词。
④匹配对应公司名
这边用到一个技巧,就是使用哈希键值对方式来做匹配。可减少遍历时间。
就是把公司名使用md5生成一个哈希值作为key值。你需要的字段作为value值。
这边我需要的是他的公司id值。则可以生成类似这样的字库数据
代码如下:
获取分词
//分词
static public function arr_list($str){
$vw= new vw();
return $vw->getWord($str);
}
具体逻辑
/**
* @param $ids_list array 公司字库哈希数据
* @param $title string 匹配标题
* @param $ids string 原有的id组
* @param $content string 文章内容
* return array 匹配到id组
* */
static public function title_to_ids($ids_list,$title,$ids="",$content=''){
if(empty($ids)){
$ids_arr=[];
}else{
$ids_arr=explode(",",$ids);
}
$str=$title;
//存在内容,则把内容也加入分词
if($content){
$str.=$content;
}
$title_list=VicWord::arr_list($str);
$n_ids=$ids_arr;
foreach ($title_list as $v){
if($v[2]!="company_name"||$v[0]=="/"){
continue;
}
$md5_name=md5($v[0]);
if(empty($ids_list[$md5_name])){
continue;
}else{
$md5_ids=explode(",",$ids_list[$md5_name]);
}
if(empty($n_ids)){
$n_ids=$md5_ids;
}else{
//合并
$n_ids=array_merge($n_ids,$md5_ids);
}
}
//排重
$n_ids=array_unique($n_ids);
return $n_ids;
}
⑤匹配完成
以上即可完成匹配,本地测试,大概一秒只能完成3~4篇文章。
匹配标题对比匹配标题+内容耗时差不多。
大家如果更好的方法,欢迎补充交流
如若有误或者有其他问题请与我交流:2359582968(微信qq同号)