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

项目启动时对载入敏感词库作为缓存(一个大map,敏感词为key,取任意值为value)。 对请求传入的文本分词,遍历分词结果,每个分词在map中查找,如果有值,则请求文本存在敏感词。

把敏感词库拼接成一个大的正则表达式,然后直接对文本匹配。

使用DFA(确定性有限状态自动机) DFA算法

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

package com.ffcs.cbox.common.utils;

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 wordIndex = new HashMap();

/*

* 初始化敏感词库

*/

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();

}

}

//敏感词词库所在目录,这里为txt文本,一个敏感词一行

String path = BanWordsUtil.class.getClassLoader()

.getResource(BAN_WORDS_LIB_FILE_NAME)

.getPath();

System.out.println(path);

List 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 searchBanWords(String content) {

if (banWordsList == null) {

try {

initBanWordsList();

} catch (IOException e) {

throw new RuntimeException(e);

}

}

List result = new ArrayList();

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 banWordList = BanWordsUtil.searchBanWords(content);

for(String s : banWordLis){

System.out.println("找到敏感词:"+s);

}

}

}

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

第一次用Markdown写作,哈哈 :)

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

  1. java.lang.IllegalArgumentException: 字符[_]在域名中永远无效。 at

    [http-nio-8080-exec-1] org.apache.coyote.AbstractProcessor.parseHost [xxx_tomcat] 是无效主机注意:更多的请求解析错误将 ...

  2. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  3. java 文件内容排序_在Java中对2个大型文本文件进行排序的最佳方法是什么?

    我正在构建一个简单的 Java应用程序,涉及从csv文件中读取信息. csv文件中的信息以这种形式出现: "ID","Description" "AB ...

  4. java 线程组作用_浅析Java中线程组(ThreadGroup类)

    一.概念 Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线 ...

  5. java xml dom4j 解析_在JAVA中怎么用DOM和DOM4j解析XML啊?

    二.XML文件 三.开始解析 public class JDOMTest { public static void main(String[] args) { // 进行对books.xml文件的JD ...

  6. java try catch嵌套_解析Java中未被捕获的异常以及try语句的嵌套使用

    Java未被捕获的异常 在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的.下面的小程序包括一个故意导致被零除错误的表达式. class Exc0 { public st ...

  7. java string最大长度_一个Java字符串中到底有多少个字符?

    作者:鸟窝 依照Java的文档, Java中的字符内部是以UTF-16编码方式表示的,最小值是 (0),最大值是(65535), 也就是一个字符以2个字节来表示,难道Java最多只能表示 65535个 ...

  8. java 异常处理发生异常_处理Java中的异常

    java 异常处理发生异常 每个程序员都希望编写一个完美的程序. 也就是说,程序运行时没有任何障碍. 好吧,如果希望是马,乞g就会骑. 除了程序员的所有愿望之外,有时还会发生无法预料的情况. 在Jav ...

  9. java web.xml 监听器_【JAVA 核心技术】java web 中的监听器

    为什么要有监听器? 监听器是用来处理一系列事件的java类,可被配置在java web项目中. 既然如此,为什么不用代码直接调用监听器? 这可能是因为J2EE规范规定的项目工程标准,用web.xml指 ...

  10. java osgi web开发_在Tomcat中使用Java Web应用程序的OSGi软件包

    我试图从Java Web应用程序调用OSGi包的方法.两者都应该在Tomcat 7上运行. 我已经写了一个正常的Java应用程序,它调用OSGi软件包中的方法,如本站所述:http://drupal. ...

最新文章

  1. PhiSpy:在细菌基因组中识别噬菌体
  2. 『数据库』震惊,某博主为吸引眼球拿出压箱底SQL总结,如果你没看那就吃亏了!(超级详细的SQL基础,你还不会的话就别学数据库了)
  3. 深度学习基础(一)起源
  4. Azure DevOps+Docker+Asp.NET Core 实现CI/CD(一 .简介与创建自己的代理池)
  5. C++_类和对象_封装_案例_立方体类_案例点和圆的关系---C++语言工作笔记039
  6. SAP License:ERP系统供应商管理都包含什么?
  7. 再谈初学者关心的ssh应用方方面面
  8. github pages markdown_赏金$25000的GitHub漏洞:通过 GitHub Pages 不安全的Kramdown配置实现多个RCE...
  9. CoreJavaE10V1P3.10 第3章 Java的基本编程结构-3.10 数组(Arrays)
  10. 什么是计算机剪贴板介绍,剪贴板在哪里,详细教您如何打开电脑剪贴板
  11. comsol matlab script,comsol script
  12. Matlab如何提取fig文件中的数据
  13. 网页播放rtsp视频流最终方案
  14. 【2018 Nature】Review Disease Primers - Epilepsy 【文献翻译】
  15. 【mysql】mysql查询结果添加固定值
  16. OSChina 周三乱弹 ——小猪佩妮,哈哈哈
  17. 第三章习题2存款利息的计算
  18. Kotlin 旅途篇(一)
  19. 低代码平台的分类及选择参考
  20. L1-057 PTA使我精神焕发 (5 分)C语言

热门文章

  1. 基于FPGA的二进制转BCD设计(附代码)
  2. golang操作sqlite3
  3. 计算机通信的应用,计算机技术在通信中的应用
  4. STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
  5. 播布客里小布老师的全部视频收集
  6. 这样的文件操作有点玄——文件流学习 ( 二 )
  7. [转]《博客园精华集》ASP.NET分册第2论筛选结果文章列表
  8. 最优秀的数据可视化案例欣赏
  9. 百度开放平台Demo提示“Key验证失败...”的问题
  10. 一文带你彻底了解电子灌封(灌胶)工艺技术