js实现提交评论等行为是过滤敏感词汇DFA算法

前言

近期在写一些评论功能的时候想到了为了防止某些用户恶意评论以及政治敏感,涉及法律等问题,需要对用户提交的评论进行过滤操作,查询了一些资料,在此记录下自己的解决方案。

阐述

DFA是一种计算模型(Deterministic Finite Automaton)也就是确定有穷自动机,它是是通过event和当前的state得到下一个state,即event+state=nextstate。由此逐步构建一个有向图,其中的节点就是状态,所以在DFA算法中只有查找和判断,没有复杂的计算,从而效率比较高。

实现


const sensitiveWordList = ['sb','草泥马']
/**
* @description
* 构造敏感词map
* @parma sensitiveWordList array  自定义的敏感词数组
*/
function 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;
}

/**
* @description
* 检查敏感词是否存在
* @private
* @param {any} txt
* @param {any} index
* @returns {flag,sensitiveWord}
*/
function 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
*/
function 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);
    console.log(txt,i, matchResult)
    if (matchResult.flag) {
      //这里我们可以返回false提示用户不能提交 或者把敏感词全部替换为*
      // return false
      console.log(`sensitiveWord:${matchResult.sensitiveWord}`);
      txt = txt.replace(new RegExp(matchResult.sensitiveWord, "gi"),'*')
    }
  }
  return txt;
}

这个过滤方法测试是没问题了,还有就是如何去自定义各种敏感词,暂时没有找到完善的数据,等找到了再补充上来。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值