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 面向对象编程基础:封装
Aug 21 Javascript
Jquery Ajax学习实例 向页面发出请求,返回XML格式数据
Mar 14 Javascript
jquery+ajax+C#实现无刷新操作数据库数据的简单实例
Feb 08 Javascript
Bootstrap 粘页脚效果
Mar 28 Javascript
vuex实现简易计数器
Oct 27 Javascript
Angular2使用jQuery的方法教程
May 28 jQuery
浅谈react-native热更新react-native-pushy集成遇到的问题
Sep 30 Javascript
angular2/ionic2 实现搜索结果中的搜索关键字高亮的示例
Aug 17 Javascript
微信小程序实现弹出层效果
May 26 Javascript
Layui数据表格跳转到指定页的实现方法
Sep 05 Javascript
15分钟上手vue3.0(小结)
May 20 Javascript
vue 在methods中调用mounted的实现操作
Aug 07 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
开发大型PHP项目的方法
2006/10/09 PHP
一个自定义位数的php多用户计数器代码
2007/03/11 PHP
《PHP编程最快明白》第四讲:日期、表单接收、session、cookie
2010/11/01 PHP
php学习之 数组声明
2011/06/09 PHP
phpphp图片采集后按原路径保存图片示例
2014/02/18 PHP
你可能不再需要JQUERY
2021/03/09 Javascript
动态样式类封装JS代码
2009/09/02 Javascript
javascript 构造函数方式定义对象
2015/01/02 Javascript
JS+CSS相对定位实现的下拉菜单
2015/10/06 Javascript
AngularJS实现textarea记录只能输入规定数量的字符并显示
2016/04/26 Javascript
JavaScript 数组- Array的方法总结(推荐)
2016/07/21 Javascript
JS获取一个未知DIV高度的方法
2016/08/09 Javascript
详解vue 组件之间使用eventbus传值
2017/10/25 Javascript
Vue封装一个简单轻量的上传文件组件的示例
2018/03/21 Javascript
js设置鼠标悬停改变背景色实现详解
2019/06/26 Javascript
vue 项目打包时样式及背景图片路径找不到的解决方式
2019/11/12 Javascript
微信小程序swiper左右扩展各显示一半代码实例
2019/12/05 Javascript
[01:32:10]NAVI vs VG Supermajor 败者组 BO3 第一场 6.5
2018/06/06 DOTA
在ubuntu16.04中将python3设置为默认的命令写法
2018/10/31 Python
OpenCV+Python识别车牌和字符分割的实现
2019/01/31 Python
python命令行参数用法实例分析
2019/06/25 Python
Python 用turtle实现用正方形画圆的例子
2019/11/21 Python
Python matplotlib修改默认字体的操作
2020/03/05 Python
解决python便携版无法直接运行py文件的问题
2020/09/01 Python
Python操作word文档插入图片和表格的实例演示
2020/10/25 Python
python实现学生信息管理系统源码
2021/02/22 Python
adidas爱尔兰官方网站:阿迪达斯运动鞋和运动服
2019/11/01 全球购物
数据库笔试题
2013/05/09 面试题
农民工创业典型事迹
2014/01/25 职场文书
安全教育演讲稿
2014/05/09 职场文书
会计专业自荐书
2014/07/08 职场文书
大学生学习十八届五中全会精神心得体会
2016/01/05 职场文书
2016大学军训心得体会
2016/01/11 职场文书
全国劳模先进事迹材料(2016精选版)
2016/02/25 职场文书
2019财务毕业实习报告
2019/06/27 职场文书
PostgreSQL通过oracle_fdw访问Oracle数据的实现步骤
2021/05/21 PostgreSQL