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 KeyDown、KeyPress和KeyUp事件的区别与联系
Dec 03 Javascript
JS中数组Array的用法示例介绍
Feb 20 Javascript
JQuery解析HTML、JSON和XML实例详解
Mar 29 Javascript
Javascript 是你的高阶函数(高级应用)
Jun 15 Javascript
jquery.multiselect多选下拉框实现代码
Nov 11 Javascript
浅谈Node.js:fs文件系统模块
Dec 08 Javascript
jQuery图片切换动画效果
Feb 28 Javascript
使用JavaScript实现表格编辑器(实例讲解)
Aug 02 Javascript
Vue实现带进度条的文件拖动上传功能
Feb 23 Javascript
微信小程序下拉框功能的实例代码
Nov 06 Javascript
解决Vue在Tomcat8下部署页面不加载的问题
Nov 12 Javascript
使用Bootstrap做一个朝代历史表
Dec 10 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实现mysql数据库分表分段备份
2015/06/18 PHP
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
2016/07/21 PHP
jquery 插件学习(二)
2012/08/06 Javascript
JavaScript高级程序设计(第3版)学习笔记2 js基础语法
2012/10/11 Javascript
SOSO地图API使用(一)在地图上画圆实现思路与代码
2013/01/15 Javascript
jquery对单选框,多选框,文本框等常见操作小结
2014/01/08 Javascript
jquery等待效果示例
2014/05/01 Javascript
jquery Validation表单验证使用详解
2020/09/12 Javascript
js实现防止被iframe的方法
2015/07/03 Javascript
javascript实现数字倒计时特效
2016/03/30 Javascript
JS实现漂亮的时间选择框效果
2016/08/20 Javascript
H5手机端多文件上传预览插件
2017/04/21 Javascript
python list使用示例 list中找连续的数字
2014/01/27 Python
浅谈python连续赋值可能引发的错误
2018/11/10 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
python中报错&quot;json.decoder.JSONDecodeError: Expecting value:&quot;的解决
2019/04/29 Python
python实现连连看辅助(图像识别)
2020/03/25 Python
Python爬虫爬取杭州24时温度并展示操作示例
2020/03/27 Python
如何查看Django ORM执行的SQL语句的实现
2020/04/20 Python
Python logging模块handlers用法详解
2020/08/14 Python
简述python Scrapy框架
2020/08/17 Python
Python求区间正整数内所有素数之和的方法实例
2020/10/13 Python
英国第一豪华护肤品牌:Elemis
2017/10/12 全球购物
List, Set, Map是否继承自Collection接口?
2016/05/16 面试题
纪检监察建议书
2014/05/19 职场文书
领导班子遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
合同和协议有什么区别?
2014/10/08 职场文书
银行贷款收入证明
2014/10/17 职场文书
2014幼儿教师个人工作总结
2014/12/03 职场文书
优秀团员事迹材料
2014/12/25 职场文书
2015七夕情人节宣传语
2015/07/14 职场文书
领导离职感言
2015/08/03 职场文书
2019年感恩励志演讲稿(收藏备用)
2019/09/11 职场文书
三年级作文之小小梦想
2019/12/06 职场文书
MySQL中一条update语句是如何执行的
2022/03/16 MySQL
【DOTA2】总决赛血虐~ XTREME GAMING vs MAGMA - OGA DOTA PIT 2022 CN
2022/04/02 DOTA