js实现敏感词过滤算法及实现逻辑


Posted in Javascript onJuly 24, 2018

最近弄了一个用户发表评论的功能,用户上传了评论,再文章下可以看到自己的评论,但作为社会主义接班人,践行社会主义核心价值观,所以给评论敏感词过滤的功能不可少,在网上找了资料,发现已经有非常成熟的解决方案。 常用的方案用这么两种

1.全文搜索,逐个匹配。这种听起来就不够高大上,在数据量大的情况下,会有效率问题,文末有比较

2.DFA算法-确定有限状态自动机 附上百科链接确定有限状态自动机

DFA算法介绍

DFA是一种计算模型,数据源是一个有限个集合,通过当前状态和事件来确定下一个状态,即 状态+事件=下一状态,由此逐步构建一个有向图,其中的节点就是状态,所以在DFA算法中只有查找和判断,没有复杂的计算,从而提高算法效率

参考文章 Java实现敏感词过滤

实现逻辑

构造数据结构

将敏感词转换成树结构,举例敏感词有着这么几个 ['日本鬼子','日本人','日本男人'] ,那么数据结构如下(图片引用参考文章)

js实现敏感词过滤算法及实现逻辑 

每个文字是一个节点,连续的节点组成一个词, 日本人 对应的就是中间的那条链,我们可以使用对象或者map来构建树,这里的栗子采用 map 构建节点,每个节点中有个状态标识,用来表示当前节点是不是最后一个,每条链路必须要有个终点节点,先来看下构建节点的流程图

js实现敏感词过滤算法及实现逻辑 

判断逻辑

先从文本的第一个字开始检查,比如 你我是日本鬼子 ,第一个字 你 ,在树的第一层找不到这个节点,那么继续找第二个字,到了 日 的时候,第一层节点找到了,那么接着下一层节点中查找 本 ,同时判断这个节点是不是结尾节点,若是结尾节点,则匹配成功了,反之继续匹配

代码实现

####构造数据结构

/**
* @description
* 构造敏感词map
* @private
* @returns
*/
private makeSensitiveMap(sensitiveWordList) {
 // 构造根节点
 const result = new Map();
 for (const word of sensitiveWordList) {
  let map = result;
  for (let i = 0; i < word.length; i++) {
   // 依次获取字
   const char = word.charAt(i);
   // 判断是否存在
   if (map.get(char)) {
    // 获取下一层节点
    map = map.get(char);
   } else {
    // 将当前节点设置为非结尾节点
    if (map.get('laster') === true) {
     map.set('laster', false);
    }
    const item = new Map();
    // 新增节点默认为结尾节点
    item.set('laster', true);
    map.set(char, item);
    map = map.get(char);
   }
  }

 }
 return result;
}

最终map结构如下

js实现敏感词过滤算法及实现逻辑 

查找敏感词

/**
* @description
* 检查敏感词是否存在
* @private
* @param {any} txt
* @param {any} index
* @returns
*/
private checkSensitiveWord(sensitiveMap, txt, index) {
 let currentMap = sensitiveMap;
 let flag = false;
 let wordNum = 0;//记录过滤
 let sensitiveWord = ''; //记录过滤出来的敏感词
 for (let i = index; i < txt.length; i++) {
  const word = txt.charAt(i);
  currentMap = currentMap.get(word);
  if (currentMap) {
   wordNum++;
   sensitiveWord += word;
   if (currentMap.get('laster') === true) {
    // 表示已到词的结尾
    flag = true;
    break;
   }
  } else {
   break;
  }
 }
 // 两字成词
 if (wordNum < 2) {
  flag = false;
 }
 return { flag, sensitiveWord };
}
/**
* @description
* 判断文本中是否存在敏感词
* @param {any} txt
* @returns
*/
public filterSensitiveWord(txt, sensitiveMap) {
 let matchResult = { flag: false, sensitiveWord: '' };
 // 过滤掉除了中文、英文、数字之外的
 const txtTrim = txt.replace(/[^\u4e00-\u9fa5\u0030-\u0039\u0061-\u007a\u0041-\u005a]+/g, '');
 for (let i = 0; i < txtTrim.length; i++) {
  matchResult = checkSensitiveWord(sensitiveMap, txtTrim, i);
  if (matchResult.flag) {
   console.log(`sensitiveWord:${matchResult.sensitiveWord}`);
   break;
  }
 }
 return matchResult;
}

效率

为了看出DFA的效率,我做了个简单的小测试,测试的文本长度为5095个汉字,敏感词词库中有2000个敏感词,比较的算法分别为 DFA算法 和 String原生对象提供的 indexOf API做比较

// 简单的字符串匹配-indexOf
ensitiveWords.forEach((word) => {
 if (ss.indexOf(word) !== -1) {
  console.log(word)
 }
})

分别将两个算法执行100次,得到如下结果

js实现敏感词过滤算法及实现逻辑 

可直观看出, DFA 的平均耗时是在1ms左右,最大为5ms; indexOf 方式的平均耗时在9ms左右,最大为14ms,所以DFA效率上还是非常明显有优势的。

总结

以上所述是小编给大家介绍的js实现敏感词过滤算法及实现逻辑,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript实现动态增加文件域表单
Feb 12 Javascript
js取得url地址参数实例
Feb 22 Javascript
HTML页面弹出居中可拖拽的自定义窗口层
May 07 Javascript
JavaSript中变量的作用域闭包的深入理解
May 12 Javascript
coffeescript使用的方式汇总
Aug 05 Javascript
jquery简单插件制作(fn.extend)完整实例
May 24 Javascript
JS中事件冒泡和事件捕获介绍
Dec 13 Javascript
Node.js连接mongodb实例代码
Jun 06 Javascript
Vue组件通信的几种实现方法
Apr 25 Javascript
js实现div色块拖动录制
Jan 16 Javascript
VUE Elemen-ui之穿梭框使用方法详解
Jan 19 Javascript
了不起的11个JavaScript代码重构最佳实践小结
Jan 11 Javascript
jQuery实现导航样式布局操作示例【可自定义样式布局】
Jul 24 #jQuery
jQuery实现菜单的显示和隐藏功能示例
Jul 24 #jQuery
Vue三种常用传值示例(父传子、子传父、非父子)
Jul 24 #Javascript
微信小程序实现横向增长表格的方法
Jul 24 #Javascript
vue中使用sessionStorage记住密码功能
Jul 24 #Javascript
Vue-router 中hash模式和history模式的区别
Jul 24 #Javascript
详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
Jul 24 #Javascript
You might like
咖啡机如何保养和日常清洁?
2021/03/03 冲泡冲煮
PHP 压缩文件夹的类代码
2009/11/05 PHP
关于PHP通用返回值设置方法
2017/03/31 PHP
PHP不使用内置函数实现字符串转整型的方法示例
2017/07/03 PHP
php intval函数用法总结
2019/04/14 PHP
JavaScript中的集合及效率
2010/01/08 Javascript
Javascript验证上传图片大小[前台处理]
2014/07/18 Javascript
js图片闪动特效可以控制间隔时间如几分钟闪动一下
2014/08/12 Javascript
深入解析jQuery中Deferred的deferred.promise()方法
2016/05/03 Javascript
js自制图片放大镜功能
2017/01/24 Javascript
Bootstrap常用组件学习(整理)
2017/03/24 Javascript
基于js 字符串indexof与search方法的区别(详解)
2017/12/04 Javascript
Angular 容器部署的方法
2018/04/17 Javascript
浅谈Angular HttpClient简单入门
2018/05/04 Javascript
vue通过点击事件读取音频文件的方法
2018/05/30 Javascript
jQuery pjax 应用简单示例
2018/09/20 jQuery
微信小程序使用setData修改数组中单个对象的方法分析
2018/12/30 Javascript
转换layUI的数据表格中的日期格式方法
2019/09/19 Javascript
Python使用Redis实现作业调度系统(超简单)
2016/03/22 Python
浅谈python 里面的单下划线与双下划线的区别
2017/12/01 Python
python实现音乐下载的统计
2018/06/20 Python
使用Django简单编写一个XSS平台的方法步骤
2019/03/25 Python
解析python实现Lasso回归
2019/09/11 Python
Python语法之精妙的十个知识点(装B语法)
2020/01/18 Python
python:批量统计xml中各类目标的数量案例
2020/03/10 Python
Speedo美国:澳大利亚顶尖泳衣制造商
2016/08/03 全球购物
如何唤起类中的一个方法
2013/11/29 面试题
外贸主管求职简历的自我评价
2013/10/23 职场文书
竞聘医务工作人员的自我评价分享
2013/11/04 职场文书
教学实验楼管理制度
2014/02/01 职场文书
见习期自我鉴定范文
2014/03/19 职场文书
单身证明格式样本
2015/06/15 职场文书
旅行社计调工作总结
2015/08/12 职场文书
python非标准时间的转换
2021/07/25 Python
Java数据结构之堆(优先队列)
2022/05/20 Java/Android
使用 DataAnt 监控 Apache APISIX的原理解析
2022/07/07 Servers