当前位置:   article > 正文

敏感词高效检测从浅到深

elasticsearch 脱敏

精选30+云产品,助力企业轻松上云!>>> hot3.png

  • 目录
  • 1.前言
  • 方案1:PHP函数
  • 方案2:正则匹配
  • 方案3:全文搜索OR分词
  • 方案4:API
  • 2.方案实战
  • 2.1创建敏感词存储数据库 
  • 2.2方案1:PHP函数
  • 2.3方案2:正则匹配
  • 2.4方案3:全文搜索OR分词
  • 2.4.1案例一:使用PHPAnalysis提取中文分词进行匹配
  • 2.4.2案例二:使用Elasticsearch全文搜索检测敏感词
  • 2.5方案4:API
  • 3.总结

1.前言

最近给公司开发商品评论系统,需求要对评论进行脱敏处理,因为之前没深入接触过,有些想当然的怎么简单怎么来,刚开始想用foreach循环匹配,但是组长一直说再想一想,想不到这里的水真深。先说说思想,我们一般人能够是通过数据库去匹配文本内容、如果敏感词库数据量大,就会出现典型的数据多匹配数据少,这样即增加开销、浪费资源,又可能增加了页面的响应时间;而符合生产环境的做法是将文本内容分词然后匹配数据库敏感词,这样少量的循环就能实现我们需要的效果,如下图所示。

up-b3ae72e48237abbd583d79d0edd5b39d0b3.png

可以看到我们传统思路是由数据库匹配文本,典型的多匹配少;所以思路逆转,少匹配多,采用文本分词手段,将需要的词匹配数据库,总的来说,当前方案一共讨论出四种。

方案1:PHP函数

优点:开发快

缺点:数据大效率低

方案2:正则匹配

优点:开发快,匹配度高

缺点:数据大效率低

方案3:全文搜索OR分词

优点:效率高

缺点:开发较复杂

方案4:API

优点:无需开发,直接调用

缺点:可能需要付费、无法自定义敏感词库

本章代码分享:https://github.com/mtdgclub/sensitiveWord

2.方案实战

2.1创建敏感词存储数据库

CREATE TABLE `t_sensitive_word` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `word` varchar(20) NOT NULL COMMENT '敏感字',
  `reason` varchar(20) DEFAULT NULL COMMENT '过滤原因',
  `is_del` tinyint(1) DEFAULT '0' COMMENT '是否删除 0不删除 1删除',
  `create_time` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='敏感词库';

2.2方案1:PHP函数

代码实现如下:

/**
 * PHP函数,处理敏感词接口
 * 作用:将敏感词变成*号,并返回处理后的文本
 */
public function dealByFuncAction()
{
    $word = $this->$_POST['appraise_msg'];
    if (!empty($word)) {

        //将敏感库初始静态化
        if (empty(self::$save_words_array)) {
            //从数据库获得敏感词库
            $m_sensitive_word = Helper::load('sensitive_word');
            $sensitiveWordArray = $m_sensitive_word->Field('word')->Select();
            //处理数组,组装
            $dealArray = [];
            foreach ($sensitiveWordArray as $k => $v) {
                $dealArray[] = $v['word'];
            }
            self::$save_words_array = $dealArray;
        }

        //给敏感词打码
        $badWords = array_combine(self::$save_words_array, array_fill(0, count(self::$save_words_array), '*'));
        $res = strtr($word, $badWords);
        $data = ['code' => 1, 'msg' => '处理成功', 'data' => $res];
    } else {
        $data = ['code' => 0, 'msg' => '参数丢失'];
    }
    Helper::response($data);
}

2.3方案2:正则匹配

/**
 * 正则匹配,处理敏感词接口
 * 作用:检测提示敏感词
 */
public function checkByRegularAction()
{
    $word = $this->$_POST['appraise_msg'];
    if (!empty($word)) {
        //去掉文本多余字符
        $flag_arr = array('•', '?', '!', '¥', '(', ')', ':', '‘', '’', '“', '”', '《', '》', ',', '…', '。', '、', 'nbsp', '】', '【', '~');
        $content_filter = preg_replace('/\s/', '', preg_replace("/[[:punct:]]/", '', strip_tags(html_entity_decode(str_replace($flag_arr, '', $word), ENT_QUOTES, 'UTF-8'))));

        //将敏感库初始静态化
        if (empty(self::$save_words_array)) {
            //从数据库获得敏感词库
            $m_sensitive_word = Helper::load('sensitive_word');
            $sensitiveWordArray = $m_sensitive_word->Field('word')->Select();
            //处理数组,组装
            $dealArray = [];
            foreach ($sensitiveWordArray as $k => $v) {
                $dealArray[] = $v['word'];
            }
            self::$save_words_array = $dealArray;
        }

        //正则匹配
        $blacklist = "/" . implode("|", self::$save_words_array) . "/i";
        self::$save_words_string = $blacklist;

        //判断
        if (preg_match(self::$save_words_string, $content_filter, $matches)) {
            $data = ['code' => 0, 'msg' => '有敏感词', 'data' => $matches[0]];
        } else {
            $data = ['code' => 1, 'msg' => '没有敏感词'];
        }
    } else {
        $data = ['code' => 0, 'msg' => '参数丢失'];
    }
    Helper::response($data);
}

另外还有正则匹配将敏感词变成*号并返回处理文本的函数dealByRegular(),详见Sensitive.php文件

2.4方案3:全文搜索OR分词

关于中文分词引擎,现在市面上提供多种方案选择,比如:SCWS、Sphinx、PHPAnalysis等等;更有结合 scws(分词引擎) + xapian(搜索引擎) 构建的开源全文搜索引擎 xunsearch、高伸缩的开源全文搜索和分析引擎Elasticsearch 等成熟的全文搜索引擎插件。更深入的有检测算法->DFA算法(全名:Deterministic Finite Automaton)即有穷自动机。其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是初态,某些状态是终态。但不同于不确定的有限自动机,DFA中不会有从同一状态出发的两条边标志有相同的符号。

下面举两个案例:

2.4.1案例一:使用PHPAnalysis提取中文分词进行匹配

下载地址:https://github.com/mtdgclub/PHPAnalysis

核心代码如下:

/**
 * Notes:返回文本的所有分词结果(一维数组)
 * @param string $content
 * @return array|string
 */
public static function getAllParticiple($content = ""){
    if (empty ( $content )) {
        return '';
    }
    require_once 'phpanalysis.class.php';
    $pa = new \PhpAnalysis ( 'utf-8', 'utf-8', false );
    $pa->SetSource($content);
    $pa->resultType=2;
    $pa->differMax=true;
    $pa->StartAnalysis();
    $arr=$pa->GetFinallyIndex();
    return $arr;
}

控制器中引用如下:

//1.引入PHPAnalysis分词引擎,提取分词数组
$Analysis = new WordAnalysis();
$result = $Analysis->getAllParticiple($word);

2.4.2案例二:使用Elasticsearch全文搜索检测敏感词

使用composer拉取Elasticsearch

{
  "require": {
    "elasticsearch/elasticsearch" : "~5.0"
  },
  "repositories": {
    "packagist": {
      "type": "composer",
      "url": "https://packagist.phpcomposer.com"
    }
  }
}

暂时放放,功力不足,看的吃力,可参考如下文档:

https://www.cnblogs.com/mzhaox/p/11210025.html

https://www.cnblogs.com/subendong/p/7308647.html

2.5方案4:API

这里以阿里云提供的敏感词API为例(点击处理跳转到API)

 /**
     * 阿里云api
     * @param $content
     * @return array|mixed|string
     */
    private function aliyunApi($content)
    {
        $host = "http://monitoring.market.alicloudapi.com";
        $path = "/neirongjiance";
        $method = "POST";
        $appcode = "150b1369d73e4aa3b3f2b22ed6cceeb4";
        $headers = array();
        array_push($headers, "Authorization:APPCODE " . $appcode);
        //根据API的要求,定义相对应的Content-Type
        array_push($headers, "Content-Type" . ":" . "application/x-www-form-urlencoded; charset=UTF-8");
        $querys = "";
        $bodys = "in={$content}";
        $url = $host . $path;

        $curl = curl_init();//初始化curl
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_URL, $url);//抓取指定网页
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_FAILONERROR, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_HEADER, true);
        if (1 == strpos("$" . $host, "https://")) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        curl_setopt($curl, CURLOPT_POSTFIELDS, $bodys);
        $result = curl_exec($curl);
        $code = curl_getinfo($curl,CURLINFO_HTTP_CODE);//取得响应码
        $data = '';
        if($code == 200){
            $data = strstr($result, '{');
            $data = json_decode($data);
        }
        curl_close($curl);
        $data = ['code' => 1, 'msg' => '敏感词API测试', 'data' => $data];
        return $data;
    }
}

3.总结

通过开发敏感词校测功能,我明白不要小看每个功能,看似简单的东西,其实一点也不简单,每个小功能都能够延伸一定的高度,拿到需求先多想、多思考,把能够想到实现方案列出来,然后让拍板人去选择哪种方案,但是呢,空闲时间也要对其他不采用的方案进行了解和学习,要做到以点盖全,而不是点就是点,加油~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/153849
推荐阅读
相关标签
  

闽ICP备14008679号