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

  1. 项目启动时对载入敏感词库作为缓存(一个大map,敏感词为key,取任意值为value)。 对请求传入的文本分词,遍历分词结果,每个分词在map中查找,如果有值,则请求文本存在敏感词。
  2. 把敏感词库拼接成一个大的正则表达式,然后直接对文本匹配。
  3. 使用DFA(确定性有限状态自动机) DFA算法

对于方案选择,在网上参考了很多别人的代码。最简单的是方法2使用正则表达式,但是据说文本一长会有很大的效率问题。关于方法3DFA算法,由于在学校的时候算法课和编译原理没有认真听讲(惭愧= =||),直接就忽略这方法了,所以最后还是决定使用方法1。
其实方法1还是有很多可以改进的方法,后来又参考了这个帖子12楼中的方法,使用索引数组加关联数组的方式,提高了检索效率,甚至连分词的步骤都省掉了。整个实现代码如下。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import org.apache.commons.lang.StringUtils;
  
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
  
import java.io.IOException;
  
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
  
  
/**
* User: eternity
* Date: 2014/8/11
* Time: 16:17
* 敏感词检测类
* 敏感词检测初始化规则:
* 将敏感词从词库载入,按照2字、3字、4字、5字等字数各生成一个敏感词哈希表。
* 在将这些哈希表组成一个数组banWordsList,数组下标表示该敏感词表字数
* banWordsList[2] = {某马:true,屏蔽:true,啦啦:true};
* banWordsList[3] = {某个马:true,三个字:true,啦啦啦:true,小广告:true};
* banWordsList[4] = {某个坏银:true,四个字符:true,哈哈哈哈:true,就爱凤姐:true};
* banWordsList[5] = {某个大法好:true,五个敏感字:true};
* 根据上面几组组敏感词,自动生成以下索引
* 生成规则为,索引名是敏感词第一个字,值是一个int
* 该int的规则为,该int转换成二进制时,第i位为1表示上面4表存在长度为i的敏感词,否则不存在长度为i的敏感词(10000)
* wordIndex = {二:0x04,三:0x08,四:0x10,五:0x20,某:0x3c,啦:0x0c,哈:0x10,小:0x08,就:0x10};
*
* 检查规则如下:
* 1,逐字检验,是否该字在wordIndex索引表中。
* 2,如果不在表中,继续检验
* 3,如果在表中,根据索引表该键的值,取此字以及此字后的若干字检验详细表banWordsList[索引词长]。
*
* 检验例子
* 有一段如下文字,检验其是否包含敏感词:
“我就打小广告,气死版主”
——检测“我”
|-不在索引表
——检测“就”
|-在索引表
|-“就”的索引值是0x10,表示有4字以“就”开头的敏感词
|-取“就”和后面的字共4个,组成“就打小广”
|-查4字敏感词表,没有这项,继续
——检测“打”
|-不在索引表
——检测“小”
|-在索引表
|-索引值是0x08,表示有3字长度的敏感词
|-取“小”和“小”后面的字,共3个字组成一个词“小广告”
|-“小广告”在3字敏感词中,此帖包含敏感词,禁止发布
*/
public class BanWordsUtil {
    // public Logger logger = Logger.getLogger(this.getClass());
    public static final int WORDS_MAX_LENGTH = 10;
    public static final String BAN_WORDS_LIB_FILE_NAME = "banWords.txt";
  
    //敏感词列表
    public static Map[] banWordsList = null;
  
    //敏感词索引
    public static Map<String, Integer> wordIndex = new HashMap<String, Integer>();
  
    /*
    * 初始化敏感词库
    */
    public static void initBanWordsList() throws IOException {
        if (banWordsList == null) {
            banWordsList = new Map[WORDS_MAX_LENGTH];
  
            for (int i = 0; i < banWordsList.length; i++) {
                banWordsList[i] = new HashMap<String, String>();
            }
        }
  
        //敏感词词库所在目录,这里为txt文本,一个敏感词一行
        String path = BanWordsUtil.class.getClassLoader()
                                        .getResource(BAN_WORDS_LIB_FILE_NAME)
                                        .getPath();
        System.out.println(path);
  
        List<String> words = FileUtils.readLines(FileUtils.getFile(path));
  
        for (String w : words) {
            if (StringUtils.isNotBlank(w)) {
                //将敏感词按长度存入map
                banWordsList[w.length()].put(w.toLowerCase(), "");
  
                Integer index = wordIndex.get(w.substring(0, 1));
  
                //生成敏感词索引,存入map
                if (index == null) {
                    index = 0;
                }
  
                int x = (int) Math.pow(2, w.length());
                index = (index | x);
                wordIndex.put(w.substring(0, 1), index);
            }
        }
    }
  
    /**
    * 检索敏感词
    * @param content
    * @return
    */
    public static List<String> searchBanWords(String content) {
        if (banWordsList == null) {
            try {
                initBanWordsList();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
  
        List<String> result = new ArrayList<String>();
  
        for (int i = 0; i < content.length(); i++) {
            Integer index = wordIndex.get(content.substring(i, i + 1));
            int p = 0;
  
            while ((index != null) && (index > 0)) {
                p++;
                index = index >> 1;
  
                String sub = "";
  
                if ((i + p) < (content.length() - 1)) {
                    sub = content.substring(i, i + p);
                } else {
                    sub = content.substring(i);
                }
  
                if (((index % 2) == 1) && banWordsList[p].containsKey(sub)) {
                    result.add(content.substring(i, i + p));
  
                    // System.out.println("找到敏感词:"+content.substring(i,i+p));
                }
            }
        }
  
        return result;
    }
  
    public static void main(String[] args) throws IOException {
        String content = "含有敏感词的测试语句。";
        BanWordsUtil.initBanWordsList();
        List<String> banWordList = BanWordsUtil.searchBanWords(content);
        for(String s : banWordLis){
         System.out.println("找到敏感词:"+s);
        }
    }
}

上面测试语文本里面其实没有敏感词(我也怕被屏蔽XD),测试的时候随便加入几个敏感词都能检测出来的。这样就实现了一个简易又快速的敏感词检测,当然如果有需要比较复杂的检测逻辑(比如说“弹吉他妈妈真漂亮”这样的),还是要用到分词工具把词拆分一下的。

来自:http://my.oschina.net/u/1010578/blog/308904

关于java中敏感词检测的一些总结相关推荐

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

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

  2. java 敏感词检测

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

  3. 敏感词检测库ToolGood.Words中IllegalWordsSearch类使用简介

      C#开源敏感词检测库ToolGood.Words中的类IllegalWordsSearch为过滤非法词(敏感词)专用类,可设置跳字长度,支持全角转忽略大小.跳词.重复词.黑名单等功能,本文对照参考 ...

  4. Java实现敏感词过滤 - IKAnalyzer中文分词工具

    IKAnalyzer 是一个开源的,基于java语言开发的轻量级的中文分词工具包. 官网: https://code.google.com/archive/p/ik-analyzer/ 本用例借助 I ...

  5. Java实现敏感词过滤

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

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

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

  7. 用java写敏感词过滤器的代码

    用java写敏感词过滤器的代码 这里采用动态代理,所以要创建proxy代理对象,利用代理,来增强某些方法(getParameter方法.getParameterMap方法.getParameterVa ...

  8. Java实现敏感词过滤双向词库完美跳过24口交换机

    Java实现敏感词过滤jar包3.0版本发布,采用双向词库,当检索语句中敏感词交错在正向词库中时,比较词汇level,如果正向词汇的level大于敏感词的level,则跳过此敏感词.完美过滤,&quo ...

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

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

最新文章

  1. 边缘计算+SDN:为物联网腾飞插上翅膀
  2. Ubuntu 进入、退出命令行的快捷键
  3. 工作中常用,实用工具推荐!
  4. JAVA——基于HttpClient的正方教务系统[1999-2020]模拟登录基本解决方案
  5. html文件本质上是一个,html文件是什么
  6. Atitit.多媒体区----web视频格式的选择总结
  7. target存放的是编译后的.class文件地方 默认情况下不会讲非class文件放入进入 如果要使用非.class文件 需要通过增加配置方式自动加入文件...
  8. Java 7中对String.substring的更改
  9. spring mvc学习(27):处理数据模型--从表单到controller传输数据续
  10. 英语四级真题作文 计算机,2019年12月英语四级写作范文:电脑
  11. python基础七之copy
  12. 0046 @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚
  13. [BUUCTF]REVERSE——相册
  14. java你应该学会什么
  15. 【Codecs系列】HEVC标准(三):大尺寸四叉树分割技术
  16. 2016ICPC北京现场赛打铁退役之旅
  17. 先正达谋定农化世界竞争格局-丰收节贸易会:座次重排
  18. Android 自定义View实现照片裁剪框与照片裁剪
  19. iOS: 设置背景颜色为渐变
  20. echarts 仿支付宝基金七日年化折线图

热门文章

  1. python连接sqlite加密_C#连接加密的Sqlite数据库的方法
  2. RedHat7/CentOS7 压缩解压命令汇总
  3. python str byte编码_Python3中内置类型bytes和str用法及byte和string之间各种编码转换 问题...
  4. C++容器适配器之priority_queue
  5. java集合-HashSet源码解析
  6. UICountingLabel实现数字变化的动画效果-b
  7. C语言的指针、链表的原理和各类操作
  8. Android系统中标准Intent的使用
  9. 使用Response.ContentType 来控制下载文件的类型
  10. 查看 SQL Server 2000 中数据表所占用的磁盘空间