PHP实现站内搜索笔记

发布于 2015-12-03 作者 [重庆SEO]

博客从wordpress更换nocolite后一直没加上搜索功能,PS:nocolite是我学习PHP并用于生产环境的PHP项目。但因为nocolite最开始是为英文网站开发的,虽然后续也增加了分词,英文搜索也比较精准,因为英文直接用空格分词,所以很明显那个分词不适合中文搜索。

说干就干,以下是PHP实现中文站内搜索的笔记。

目标要求:

1.尽量精准
2.尽量少的代码
根据这个目标要求,就扩展一下最基础的mysql的like语句直接匹配字符串,通过分词使其更精准一点。

要点:

1.只搜索标题
2.分词暂时使用中文分词api

通过API 字符串得到分词,需要去掉重复的单词,以及单个的中文字符减少非重要关键词。下面是SCWS的中文分词API实现方法。

//http://www.xunsearch.com/scws/api.php
function scws_api($str){
  $url = 'http://www.xunsearch.com/scws/api.php';
  $data = array(
    'data'=>$str,
    'respond'=>'json',
    'ignore'=>'yes',
  );

  $json_data = postData($url, $data);
  $array = json_decode($json_data,true);

  if ($array['status']=='ok'){
    $array=$array['words'];
    foreach($array as $v){
      //排除单个汉字,缩小范围
      if($v['attr']!='en' && $v['len']<4){
      }else{
        $arr[]=$v['word'];
      }
    }
  }else{
    return array($str);
  }
  return $arr;
}


function postData($url, $data){
  $ch = curl_init();
  $timeout = 300;
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  $handles = curl_exec($ch);
  curl_close($ch);
  return $handles;
}

获取到分词后,接下来就是根据分词拼接sql的like字符串了,重点在于关键词两两匹配,必须同时满足2个分词。能适当提高精准度。

//分词拼接SQL进行搜索
$array=scws_api($keywords);
//去重复
$array=array_unique($array);
//全匹配 and
foreach($array as $v){
$where1.="" and title like '%$v%'";
}
//两两匹配
$result = array();
foreach ( $array as $v1){
  foreach ( $array as $v2){
    if($v1!=$v2){
      $where2.= " or (title like '%$v1%' and title like '%$v2%')";
    }
  }
}
//拼接
$where="1".$where1.$where2;
虽然比较简陋且有些许缺陷,但好歹算比较满意了。有了搜索范围,接下来就简单了,你可以试下本站右上角的搜索。

----更新补充-------------------------------

不用API,使用PHP扩展可以很大程度提高分词速度:Linux安装中文分词SCWS的PHP扩展