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 相关文章推荐
用js实现手把手教你月入万刀(转贴)
Nov 07 Javascript
JavaScript 使用技巧精萃(.net html
Apr 25 Javascript
js和as的稳定传值问题解决
Jul 14 Javascript
JS使用getComputedStyle()方法获取CSS属性值
Apr 23 Javascript
js获取当前页面的url网址信息
Jun 12 Javascript
js实现鼠标感应图片展示的方法
Feb 27 Javascript
利用jQuery及AJAX技术定时更新GridView的某一列数据
Dec 04 Javascript
Javascript实现的StopWatch功能示例
Jun 13 Javascript
浅析node.js的模块加载机制
May 25 Javascript
基于javascript实现贪吃蛇经典小游戏
Apr 10 Javascript
JavaScript实现简单贪吃蛇效果
Mar 09 Javascript
详解Typescript里的This的使用方法
Jan 08 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
Javascript UrlDecode函数代码
2010/01/09 Javascript
Js 回车换行处理的办法及replace方法应用
2013/01/24 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
2014/05/28 Javascript
JavaScript使用setInterval()函数实现简单轮询操作的方法
2015/02/02 Javascript
jQuery实现转动随机数抽奖效果的方法
2015/05/21 Javascript
jQuery使用$获取对象后检查该对象是否存在的实现方法
2016/09/04 Javascript
jQuery图片前后对比插件beforeAfter用法示例【附demo源码下载】
2016/09/20 Javascript
JS短信验证码倒计时功能的实现(没有验证码,只有倒计时)
2016/10/27 Javascript
探索Vue.js component内容实现
2016/11/03 Javascript
JS给按钮添加跳转功能类似a标签
2017/05/30 Javascript
vue+element-ui动态生成多级表头的方法
2018/08/28 Javascript
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
使用element-ui table expand展开行实现手风琴效果
2019/03/15 Javascript
Vue开发环境中修改端口号的实现方法
2019/08/15 Javascript
VUE注册全局组件和局部组件过程解析
2019/10/10 Javascript
JavaScript布尔运算符原理使用解析
2020/05/06 Javascript
基于JavaScript实现控制下拉列表
2020/05/08 Javascript
通过实例解析vuejs如何实现调试代码
2020/07/16 Javascript
python中字符串前面加r的作用
2015/06/04 Python
浅析Python中的for 循环
2016/06/09 Python
Python读取数据集并消除数据中的空行方法
2018/07/12 Python
详解Python3.6的py文件打包生成exe
2018/07/13 Python
python3对接mysql数据库实例详解
2019/04/30 Python
pymysql 开启调试模式的实现
2019/09/24 Python
iPython pylab模式启动方式
2020/04/24 Python
Django QuerySet查询集原理及代码实例
2020/06/13 Python
python 如何读、写、解析CSV文件
2021/03/03 Python
CSS3之多背景background使用示例
2013/10/18 HTML / CSS
美国运动鞋和服装网上商店:YCMC
2018/09/15 全球购物
大学学年自我鉴定
2013/10/28 职场文书
2015年店长工作总结范文
2015/04/08 职场文书
楚门的世界观后感
2015/06/03 职场文书
2016教师节问候语
2015/11/10 职场文书
2019年销售人员的职业生涯规划书
2019/03/25 职场文书
mysql查询的控制语句图文详解
2021/04/11 MySQL
Python趣味实战之手把手教你实现举牌小人生成器
2021/06/07 Python