PHP

PHP如何实现分词并应用于文章搜索:完整指南

silverwq
2022-05-20 / 0 评论 / 366 阅读 / 正在检测是否收录...

一、概述

php的分词库,大致有以下几个:

  1. Jieba 分词库,github地址,好像比较耗内存
  2. SCWS 分词,无法自己扩展,貌似要钱
  3. jieba 扩展,中文名叫结巴分词,感觉比较轻量,速度也挺快的,github地址,本教程使用这个,这个扩展可以自定义词库,不过我好像没有成功过。

二、安装jieba 扩展

  1. 按如下步骤安装即可:
    
    git clone https://github.com/jonnywang/phpjieba.git
    cd phpjieba/cjieba
    make

cd ..
phpize
./configure
make
make install

2. ini配置
```ini
extension=jieba.so
jieba.enable=1
;这个目录克隆的目录+phpjieba/cjieba/dict,本教程是克隆到/usr/local/php7.4目录
jieba.dict_path=/usr/local/php7.4/phpjieba/cjieba/dict

三、拓展知识

  1. 把分词用作mysql的搜索当中,例如分词关键词是“下载”,那么下面的sql的意思是,文章标题中出现下载的权重加2分,文章内容中出现下载的权重加一分,然后按总分数降序排序。

    SELECT * FROM blog_contents
    WHERE
    (
     2 * SIGN(INSTR(blog_contents.title, "下载"))+ 
     SIGN(INSTR(blog_contents.text, "下裁"))
    )
    ORDER BY
    (
     2 * SIGN(INSTR(blog_contents.title, "下载"))+ 
     SIGN(INSTR(blog_contents.text, "下裁"))
    )  
    DESC;

    a). 其中SIGN(x) 返回参数的符号,x 的值为负、零和正时返回结果依次为 -1、0 和 1。
    b). 函数instr(filed,str),作用是返回str子字符串在filed字符串的第一次出现的位置。当instr(filed,str)=0时,表示子符串str不存在于字符串filed中,因此可以用来实现mysql中的模糊查询,与like用法类似。如下:

    instr(filed,str) > 0 ⇒ file like '%str%'
    instr(filed,str) = 1 ⇒ file like  'str%'
    instr(filed,str) = 0 ⇒ file not like  '%str%'
  2. php总结合jieba扩展

    // 注意有第三个参数,第一个参数是关键词,第二个参数是动作,第三个参数是限制数量。以下参数配置是我认为比较好的。
    $result = jieba($keywords,1);
    $result = array_filter($result, function ($value) {// 去除空格
    $value = trim($value);
    return $value == true;// 为true的将保留值
    });
    $search = [];
    foreach ($result as $keyWorld) {
     array_push($search,"2*SIGN(INSTR(table.contents.title, '{$keyWorld}'))");
     array_push($search,"SIGN(INSTR(table.contents.text, '{$keyWorld}'))");
    }
    $searchQuery = '('.implode('+',$search).')';
    $sql = "SELECT * FROM blog_contents WHERE {$searchQuery} ORDER BY {$searchQuery} DESC;

四、注意

这个分词扩展如果开启来的话,我在本地服务看单个php-fpm进程的内存占用达到300M左右。不开这个扩展的时候,一个php-fpm的内存也就10M左右。不过好像线上服务器,看了下开不开这个扩展,内存基本都维持在10M左右,不知道什么原因。总之实际内存占用情况,大家可以自己看下,酌情使用。
不过好像还有一个,有redis来存储分词词库的版本,估计对内存比较友好,https://github.com/jonnywang/goredisjieba

五、拓展阅读

也可以用第三方的分词服务,比如:

  1. elasticseach
  2. zinc,github地址,这个是用go实现的,省内存,不知道支不支持分布式
0

评论 (0)

取消