在网上看到好多的敏感词检测,发现都是在推荐某某算法,但是敏感词全是利用文本去存放。在项目中不能很好的进行维护和管理(个人看法)。

本文的敏感词的检测方式还是DFA算法检测,不过敏感词存放地址放入了Redis的中,方便维护和更新。

1.使用redis进行敏感词存储

将文本中的敏感词读取出来然后存放到redis的中。使用设置类型进行存储(去重)

代码略...

2.使用二叉树进行敏感词分类

跟网上大部分的代码一致(不过本文中是使用单例模式进行调用,只在第一次调用时进行redis读取操作存放到项目中)

package com.cctv.aisys.utils.words;import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSONObject;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;public class BadWordUtil {public static Set<String> words;public static Map<String, String> wordMap;public static int minMatchTYpe = 1; // 最小匹配规则public static int maxMatchType = 2; // 最大匹配规则private static BadWordUtil badWordUtil;private final Logger logger = LoggerFactory.getLogger(BadWordUtil.class);private BadWordUtil() {}/*** 生成敏感词缓存* @param jedisPool*/private BadWordUtil(JedisPool jedisPool) {logger.info("正在生成敏感词缓存");BadWordUtil2.words = readTxtByLine(jedisPool);addBadWordToHashMap(BadWordUtil2.words);logger.info("敏感词缓存成功");}public static BadWordUtil getBadWordUtil(JedisPool jedisPool) {if (badWordUtil == null) {badWordUtil = new BadWordUtil(jedisPool);}return badWordUtil;}private Set<String> readTxtByLine(JedisPool jedisPool) {Set<String> keyWordSet = new HashSet<String>();Jedis jedis = jedisPool.getResource();keyWordSet = jedis.smembers("sensitive");return keyWordSet;}/*** 检查文字中是否包含敏感字符,检查规则如下:<br>* * @param txt* @param beginIndex* @param matchType* @return,如果存在,则返回敏感词字符的长度,不存在返回0* @version 1.0*/@SuppressWarnings({ "rawtypes" })private int checkBadWord(String txt, int beginIndex, int matchType) {boolean flag = false; // 敏感词结束标识位:用于敏感词只有1位的情况int matchFlag = 0; // 匹配标识数默认为0char word = 0;Map nowMap = wordMap;for (int i = beginIndex; i < txt.length(); i++) {word = txt.charAt(i);nowMap = (Map) nowMap.get(word); // 获取指定keyif (nowMap != null) { // 存在,则判断是否为最后一个matchFlag++; // 找到相应key,匹配标识+1if ("1".equals(nowMap.get("isEnd"))) { // 如果为最后一个匹配规则,结束循环,返回匹配标识数flag = true; // 结束标志位为trueif (minMatchTYpe == matchType) { // 最小规则,直接返回,最大规则还需继续查找break;}}} else { // 不存在,直接返回break;}}/** “粉饰”匹配词库:“粉饰太平”竟然说是敏感词 “个人”匹配词库:“个人崇拜”竟然说是敏感词 if(matchFlag < 2 && !flag){* matchFlag = 0; }*/if (!flag) {matchFlag = 0;}return matchFlag;}/*** 判断文字是否包含敏感字符* * @param txt*            文字* @param matchType*            匹配规则 1:最小匹配规则,2:最大匹配规则* @return 若包含返回true,否则返回false* @version 1.0*/@SuppressWarnings("unused")private boolean isContaintBadWord(String txt, int matchType) {boolean flag = false;for (int i = 0; i < txt.length(); i++) {int matchFlag = checkBadWord(txt, i, matchType); // 判断是否包含敏感字符if (matchFlag > 0) { // 大于0存在,返回trueflag = true;}}return flag;}/*** 替换敏感字字符* * @param txt* @param matchType* @param replaceChar*            替换字符,默认** @version 1.0*/@SuppressWarnings("unused")private String replaceBadWord(String txt, int matchType, String replaceChar) {String resultTxt = txt;Set<String> set = getBadWord(txt, matchType); // 获取所有的敏感词Iterator<String> iterator = set.iterator();String word = null;String replaceString = null;while (iterator.hasNext()) {word = iterator.next();replaceString = getReplaceChars(replaceChar, word.length());resultTxt = resultTxt.replaceAll(word, replaceString);}return resultTxt;}/*** 获取文字中的敏感词* * @param txt*            文字* @param matchType*            匹配规则 1:最小匹配规则,2:最大匹配规则* @return* @version 1.0*/private Set<String> getBadWord(String txt, int matchType) {Set<String> sensitiveWordList = new HashSet<String>();for (int i = 0; i < txt.length(); i++) {int length = checkBadWord(txt, i, matchType); // 判断是否包含敏感字符if (length > 0) { // 存在,加入list中sensitiveWordList.add(txt.substring(i, i + length));i = i + length - 1; // 减1的原因,是因为for会自增}}return sensitiveWordList;}/*** 获取替换字符串* * @param replaceChar* @param length* @return* @version 1.0*/private String getReplaceChars(String replaceChar, int length) {String resultReplace = replaceChar;for (int i = 1; i < length; i++) {resultReplace += replaceChar;}return resultReplace;}/*** TODO 将我们的敏感词库构建成了一个类似与一颗一颗的树,这样我们判断一个词是否为敏感词时就大大减少了检索的匹配范围。* * @param keyWordSet*            敏感词库* @author yqwang0907* @date 2018年2月28日下午5:28:08*/@SuppressWarnings({ "unchecked", "rawtypes" })private void addBadWordToHashMap(Set<String> keyWordSet) {wordMap = new HashMap(keyWordSet.size()); // 初始化敏感词容器,减少扩容操作String key = null;Map nowMap = null;Map<String, String> newWorMap = null;// 迭代keyWordSetIterator<String> iterator = keyWordSet.iterator();while (iterator.hasNext()) {key = iterator.next(); // 关键字nowMap = wordMap;for (int i = 0; i < key.length(); i++) {char keyChar = key.charAt(i); // 转换成char型Object wordMap = nowMap.get(keyChar); // 获取if (wordMap != null) { // 如果存在该key,直接赋值nowMap = (Map) wordMap;} else { // 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个newWorMap = new HashMap<String, String>();newWorMap.put("isEnd", "0"); // 不是最后一个nowMap.put(keyChar, newWorMap);nowMap = newWorMap;}if (i == key.length() - 1) {nowMap.put("isEnd", "1"); // 最后一个}}}}/*** 敏感词检测调用接口* @param content 检测文本* @return 检测结果*/public JSONObject check(String content) {JSONObject json = new JSONObject();long start = System.currentTimeMillis();Set<String> set = BadWordUtil2.getBadWord(content, 5);long end = System.currentTimeMillis();json.put("keyNum", BadWordUtil2.wordMap.size());json.put("result", set);json.put("time", end - start);boolean flag = true;if (set != null && set.size() > 0) {flag = false;}json.put("flag", flag);return json;}/*** 清空敏感词*/public void clear() {badWordUtil = null;logger.info("敏感词缓存已清空");}

3.输入内容进行敏感词检测

@Testpublic void main1() {String string = "一直以为写小说是作家的事,普通如我这样的业余写作爱好者,写小说那只能是梦想。六合彩";BadWordUtil badWordUtil = BadWordUtil.getBadWordUtil(jedisPool);JSONObject json = badWordUtil.check(string);System.out.println(json);//输出 :{"result":["六合彩"],"flag":false,"keyNum":1701,"time":1}

4.向redis中添加敏感词并更新程序中的敏感词

单例模式下,销毁当前对象,然后再生成一个新对象,实现敏感词的更新。

Jedis resource = jedisPool.getResource();
Long sadd = resource.sadd("sensitive", "大乐透七彩");
System.out.println(sadd);
BadWordUtil badWordUtil = BadWordUtil.getBadWordUtil(jedisPool);
badWordUtil.clear();  //单例模式 销毁对象,让他重新new一个对象,实现敏感词的更新
//输出1

24万的敏感词 加载一次只需要4秒。检测时间1-2毫秒。性能是相当的快,而且方便维护与管理

java 敏感词检测相关推荐

  1. 关于java中敏感词检测的一些总结

    之前项目里客户提出一个需求,需要对系统中使用文本转化成语音发送的功能进行敏感词检测,禁止用户提交有敏感词的语音.通过查询各方面资料,整理了大概几种方案: 项目启动时对载入敏感词库作为缓存(一个大map ...

  2. 一种基于DFA算法的敏感词检测JAVA程序片段

    本文章提供一种基于DFA算法的敏感词检测JAVA程序片段,如下: 1.构造多叉树数据结构 import org.jetbrains.annotations.NotNull;/*** 多叉树* @aut ...

  3. 写一个高性能的敏感词检测组件

    最近写了一个高性能的敏感词检测组件[ToolGood.Words]. 一.高性能,它的效率到底有多快? 如果将正则表达式的算法效率设为1,高性能可达到正则表达式的1.5万倍. 二.选一个巧妙的算法: ...

  4. Java 敏感词过滤,Java 敏感词替换,Java 敏感词工具类

    Java 敏感词过滤,Java 敏感词替换,Java 敏感词工具类 =========================== ©Copyright 蕃薯耀 2017年9月22日 http://fansh ...

  5. Go+PHP实现敏感词检测

    概述 广告,敏感词检测一直以来都是让人头疼的话题,仅仅通过添加敏感词列表是解决不了问题的.今天封禁了这个词,明天又会有新的违禁词冒出来,比起愚公无穷尽的子孙更甚. 敏感词匹配这种治标不治本的方法,在一 ...

  6. php访问小程序内容检测接口,关于小程序接入敏感词检测接口的坑

    接入 msgSecCheck 接口47001 错误码踩坑! 这是官方文档要求,写的有些笼统,根据开发者社区提供需要进行编码后在传参,以下为 php 代码示例/** * 敏感词检测 * @param $ ...

  7. 免费敏感词检测API

    免费敏感词检测,免费文本内容审核, 不用什么注册key,下载到本地直接运行,直接http json查询. 下载地址 ​​https://github.com/bosnzt/wordscheck​​ ​ ...

  8. Java 敏感词过滤(DFA有穷自动机)

    Java 敏感词过滤 DFA有穷自动机 初始化敏感词 构建树 查询 完整代码如下 后记 初始化敏感词 使用set集合,可以查询数据库. /*** 初始化值* @return*/private stat ...

  9. 测试.net开源敏感词检测库ToolGood.Words

      微信公众号"DotNet"看到介绍.net开源敏感词检测库ToolGood.Words的文章<.NET Core一款高性能敏感词检测开源库>,根据参考文献2中的测试 ...

最新文章

  1. JAVA线程六种状态_Java:线程的六种状态及转化
  2. sqlalchemy mysql配置中怎么设置utf8_sqlalchemy 的设置及使用
  3. tkinter窗口居中方法
  4. 2014年第五届蓝桥杯C/C++ A组国赛 —— 第四题:排列序数
  5. linux 源码 目录,Linux系统主要目录及kernel源代码目录
  6. 常用的好用的window工具
  7. ubuntu ip设置
  8. 大道至简: 拉新、促活和留存
  9. setsockopt设置套接口选项
  10. kibana设置中文
  11. 领导问“BUG解决了没有”,吾一听就知道完蛋了
  12. 你所不知道的NVMe SSD固态硬盘读写速度及国货的惊喜--基于FPGA的速度测试
  13. 销量下降,到底应该怎么分析?!
  14. K210入门,用wifi通讯
  15. php移动插屏如何做,每天说移动营销,你懂插屏广告吗?
  16. C语言和win32绿色鼠标连点器,带代码(Windows)
  17. 第三方数据源大型库| CnOpenData全球专利及引用被引用数据
  18. 微信小程序Demo组件大全(对话框、指示器、五星评分,画廊,影院座位……
  19. C标准库函数mkfifo()(进程相关函数)
  20. 什么是CRM、ERP、BPM?

热门文章

  1. 【Xavier】 SDKmanager无法识别/使用Flash.sh【刷机】/【硬盘扩容安装】NVME SSD【踩坑大保底】
  2. Attention机制
  3. zipslack安装方法(安装在ext3上成功运行)(转)
  4. [原] RStudio Spark/Leaflet 与 GIS 最佳实践
  5. “use strict“是什么? 使用它有什么优缺点?
  6. 正则判断时间年月日格式
  7. 如何做好迭代回顾 2/4
  8. Janet八股文集锦
  9. 有关Oracle数据库的几个神话
  10. ___73__OleDbDataAdapter读取Access数据__到DataSet中来