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 12 Javascript
Firefox中使用outerHTML的2种解决方法
Jun 07 Javascript
jQuery实现视频作为全屏幕背景
Dec 18 Javascript
jQuery复制表单元素附源码分享效果演示
Sep 30 Javascript
JS获取地址栏参数的两种方法(简单实用)
Jun 14 Javascript
js实现登录与注册界面
Nov 01 Javascript
基于打包工具Webpack进行项目开发实例
May 29 Javascript
如何解决.vue文件url引用文件的问题
Jan 18 Javascript
[jQuery] 事件和动画详解
Mar 05 jQuery
Javascript组合继承方法代码实例解析
Apr 02 Javascript
js实现星星打分效果
Jul 05 Javascript
JS寄快递地址智能解析的实现代码
Jul 16 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
全国FM电台频率大全 - 26 西藏自治区
2020/03/11 无线电
PHP和XSS跨站攻击的防范
2007/04/17 PHP
PHP中session跨子域的三种实现方法
2016/07/25 PHP
使用新的消息弹出框blackbirdjs
2008/10/16 Javascript
JavaScript Array扩展实现代码
2009/10/14 Javascript
javascript 基础篇3 类,回调函数,内置对象,事件处理
2012/03/14 Javascript
jQuery的:parent选择器定义和用法
2014/07/01 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
2015/03/24 Javascript
纯javascript实现的小游戏《Flappy Pig》实例
2015/07/27 Javascript
JS+CSS实现自动切换的网页滑动门菜单效果代码
2015/09/14 Javascript
jQuery 的 ready()的纯js替代方法
2016/11/20 Javascript
如何处理JSON中的特殊字符
2016/11/30 Javascript
AngularJS中的JSONP实例解析
2016/12/01 Javascript
Easyui和zTree两种方式分别实现树形下拉框
2017/08/04 Javascript
解决vue的变量在settimeout内部效果失效的问题
2018/08/30 Javascript
JavaScript实现学生在线做题计时器功能
2018/12/05 Javascript
微信小程序如何实现全局重新加载
2019/06/05 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
2019/09/03 Javascript
node.js开发辅助工具nodemon安装与配置详解
2020/02/06 Javascript
javascript实现简易数码时钟
2020/03/30 Javascript
Python基于正则表达式实现检查文件内容的方法【文件检索】
2017/08/30 Python
python tensorflow学习之识别单张图片的实现的示例
2018/02/09 Python
pandas 根据列的值选取所有行的示例
2018/11/07 Python
python爬虫 模拟登录人人网过程解析
2019/07/31 Python
python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例
2020/03/08 Python
Python3.7 读取音频根据文件名生成脚本的代码
2020/04/07 Python
Python pandas对excel的操作实现示例
2020/07/21 Python
英国Zoro工具:手动工具,电动工具和个人防护用品
2016/11/02 全球购物
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
农业资源与环境专业自荐信范文
2013/12/30 职场文书
优秀学生干部个人事迹材料
2014/06/02 职场文书
微笑服务标语
2014/06/24 职场文书
校园新闻广播稿5篇
2014/10/10 职场文书
2015年行政执法工作总结
2015/05/23 职场文书
趣味运动会赞词
2015/07/22 职场文书
logback 实现给变量指定默认值
2021/08/30 Java/Android