当前位置:   article > 正文

敏感词过滤的实现方案

敏感词过滤的实现方案

1.采用DFA算法实现

  1. /**
  2. * 敏感词过滤工具类
  3. *
  4. * @author maple
  5. */
  6. import java.util.HashMap;
  7. import java.util.HashSet;
  8. import java.util.Map;
  9. import java.util.Set;
  10. @SuppressWarnings({"unchecked", "rawtypes"})
  11. public class SensitiveFilterUtil {
  12. /**
  13. * 敏感词集合
  14. */
  15. public static HashMap sensitiveWordMap;
  16. /**
  17. * 初始化敏感词库,构建DFA算法模型
  18. */
  19. public static void initContext(HashSet<String> set) {
  20. initSensitiveWordMap(set);
  21. }
  22. /**
  23. * 初始化敏感词库,构建DFA算法模型
  24. *
  25. * @param sensitiveWordSet 敏感词库
  26. */
  27. private static void initSensitiveWordMap(Set<String> sensitiveWordSet) {
  28. //初始化敏感词容器,减少扩容操作
  29. sensitiveWordMap = new HashMap<String, String>(sensitiveWordSet.size());
  30. Map<Object, Object> temp;
  31. Map<Object, Object> newWorMap;
  32. //遍历sensitiveWordSet
  33. for (String key : sensitiveWordSet) {
  34. temp = sensitiveWordMap;
  35. for (int i = 0; i < key.length(); i++) {
  36. //转换成char型
  37. char keyChar = key.charAt(i);
  38. //库中获取关键字
  39. Object wordMap = temp.get(keyChar);
  40. //如果存在该key,直接赋值,用于下一个循环获取
  41. if (wordMap != null) {
  42. temp = (Map) wordMap;
  43. } else {
  44. //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
  45. newWorMap = new HashMap<>();
  46. //不是最后一个
  47. newWorMap.put("isEnd", "0");
  48. temp.put(keyChar, newWorMap);
  49. temp = newWorMap;
  50. }
  51. //最后一个
  52. if (i == key.length() - 1) temp.put("isEnd", "1");
  53. }
  54. }
  55. }
  56. /**
  57. * 判断文字是否包含敏感字符
  58. * <p>
  59. * 文本
  60. * <p>
  61. * 若包含返回true,否则返回false
  62. */
  63. public static boolean contains(String txt) {
  64. boolean flag = false;
  65. for (int i = 0; i < txt.length(); i++) {
  66. int matchFlag = checkSensitiveWord(txt, i); //判断是否包含敏感字符
  67. if (matchFlag > 0) {//大于0存在,返回true
  68. flag = true;
  69. }
  70. }
  71. return flag;
  72. }
  73. /**
  74. * 检查文字中是否包含敏感字符,检查规则如下:
  75. *
  76. * @param txt
  77. * @param beginIndex
  78. * @return 如果存在, 则返回敏感词字符的长度, 不存在返回0
  79. */
  80. private static int checkSensitiveWord(String txt, int beginIndex) {
  81. //敏感词结束标识位:用于敏感词只有1位的情况
  82. boolean flag = false;
  83. //匹配标识数默认为0
  84. int matchFlag = 0;
  85. char word;
  86. Map nowMap = sensitiveWordMap;
  87. for (int i = beginIndex; i < txt.length(); i++) {
  88. word = txt.charAt(i);
  89. //获取指定key
  90. nowMap = (Map) nowMap.get(word);
  91. if (nowMap != null) {//存在,则判断是否为最后一个
  92. //找到相应key,匹配标识+1
  93. matchFlag++;
  94. //如果为最后一个匹配规则,结束循环,返回匹配标识数
  95. if ("1".equals(nowMap.get("isEnd"))) {
  96. //结束标志位为true
  97. flag = true;
  98. }
  99. } else {//不存在,直接返回
  100. break;
  101. }
  102. }
  103. if (matchFlag < 2 || !flag) {//长度必须大于等于1,为词
  104. matchFlag = 0;
  105. }
  106. return matchFlag;
  107. }
  108. /**
  109. * 获取文字中的敏感词
  110. * <p>
  111. * txt文字
  112. */
  113. public static HashSet getSensitiveWord(String txt) {
  114. HashSet hashSet = new HashSet();
  115. for (int i = 0; i < txt.length(); i++) {
  116. //判断是否包含敏感字符
  117. int length = checkSensitiveWord(txt, i);
  118. if (length > 0) {//存在,加入list中
  119. hashSet.add(txt.substring(i, i + length));
  120. i = i + length - 1;//减1的原因,是因为for会自增
  121. }
  122. }
  123. return hashSet;
  124. }
  125. /**
  126. * context是要校验的内容。返回结果是list,为空说明没有敏感词
  127. *
  128. * @param context
  129. * @return
  130. */
  131. public static HashSet checkTxt(String context, HashSet<String> set) {
  132. initContext(set);
  133. //包含敏感词返回所有敏感词数据
  134. return getSensitiveWord(context);
  135. }
  136. }

2.违规词实体类

  1. /**
  2. * 敏感词对象 disk_sensitive_word
  3. *
  4. * @author maple
  5. * @date 2024-04-17
  6. */
  7. public class DiskSensitiveWord extends BaseEntity
  8. {
  9. private static final long serialVersionUID = 1L;
  10. /** 自增id */
  11. private Long id;
  12. /** 添加人 */
  13. @Excel(name = "添加人")
  14. private String userName;
  15. /** 敏感词 */
  16. @Excel(name = "敏感词")
  17. private String sensitiveWord;
  18. public void setId(Long id)
  19. {
  20. this.id = id;
  21. }
  22. public Long getId()
  23. {
  24. return id;
  25. }
  26. public void setUserName(String userName)
  27. {
  28. this.userName = userName;
  29. }
  30. public String getUserName()
  31. {
  32. return userName;
  33. }
  34. public void setSensitiveWord(String sensitiveWord)
  35. {
  36. this.sensitiveWord = sensitiveWord;
  37. }
  38. public String getSensitiveWord()
  39. {
  40. return sensitiveWord;
  41. }
  42. @Override
  43. public String toString() {
  44. return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
  45. .append("id", getId())
  46. .append("userName", getUserName())
  47. .append("sensitiveWord", getSensitiveWord())
  48. .append("createTime", getCreateTime())
  49. .append("updateTime", getUpdateTime())
  50. .toString();
  51. }
  52. }

3.测试用例,数据来源可以通过数据库,文件获取,有需要违规词库的联系我哈

  1. HashSet<String> set = this.selectDiskSensitiveWordAllList()
  2. .stream().map(DiskSensitiveWord::getSensitiveWord).collect(Collectors.toCollection(HashSet::new));
  3. HashSet hashSet = SensitiveFilterUtil.checkTxt(text, set);
  4. if (CollectionUtil.isEmpty(hashSet)) return false;
  5. throw new ServiceException("有敏感词 "+ hashSet);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/769930
推荐阅读
相关标签
  

闽ICP备14008679号