这篇文章,分享一个开源项目:sensitive-word

Github 地址:https://github.com/houbb/sensitive-word

sensitive-word 是一个功能强大的 Java 敏感词过滤框架,它不仅提供了基础的敏感词检测功能,还支持单词标签分类分级、繁简体互换、全角半角互换、汉字转拼音、模糊搜索等高级特性。

它的核心特性如下:

  • 高性能: 基于 DFA 算法,匹配效率极高
  • 标签分类: 支持敏感词分类分级管理
  • 字符处理: 支持繁简体、全角半角互换
  • 模糊搜索: 支持拼音、形似字等模糊匹配
  • 开箱即用: 简单配置即可快速集成

1 基础使用

<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>sensitive-word</artifactId>
<version>0.29.2</version>
</dependency>

SensitiveWordHelper 作为敏感词的工具类,核心方法如下:

示例代码:

import com.github.houbb.sensitive.word.core.SensitiveWordHelper;

public class BasicExample {
public static void main(String[] args) {
String text = "这是一个包含赌博和毒品等不良内容的测试文本";
// 检测是否包含敏感词
boolean hasSensitive = SensitiveWordHelper.contains(text);
System.out.println("是否包含敏感词: " + hasSensitive); // 查找所有敏感词
List<String> sensitiveWords = SensitiveWordHelper.findAll(text);
System.out.println("发现的敏感词: " + sensitiveWords); // 替换敏感词
String cleanedText = SensitiveWordHelper.replace(text);
System.out.println("清洗后文本: " + cleanedText); // 使用指定字符替换
String customReplaced = SensitiveWordHelper.replace(text, '*');
System.out.println("自定义替换: " + customReplaced);
}
}

执行结果:

2 特殊处理

sensitive-word 为了尽可能的提升敏感词命中率,针对各种各种情况做了处理。

1、忽略大小写

final String text = "fuCK the bad words.";

String word = SensitiveWordHelper.findFirst(text);
Assert.assertEquals("fuCK", word);

2、忽略圆角半角

final String text = "fuck the bad words.";

String word = SensitiveWordHelper.findFirst(text);
Assert.assertEquals("fuck", word);

3、忽略数字的写法

final String text = "这个是我的微信:9⓿二肆⁹₈③⑸⒋➃㈤㊄";

List<String> wordList = SensitiveWordBs.newInstance().enableNumCheck(true).init().findAll(text);
Assert.assertEquals("[9⓿二肆⁹₈③⑸⒋➃㈤㊄]", wordList.toString());

4、忽略繁简体

final String text = "我爱我的祖国和五星紅旗。";

List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[五星紅旗]", wordList.toString());

5、忽略英文的书写格式

final String text = "Ⓕⓤc⒦ the bad words";

List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[Ⓕⓤc⒦]", wordList.toString());

6、忽略重复词

final String text = "ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦ the bad words";

List<String> wordList = SensitiveWordBs.newInstance()
.ignoreRepeat(true)
.init()
.findAll(text);
Assert.assertEquals("[ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦]", wordList.toString());

3 更多检测策略

sensitive-word 支持数字、邮箱、URL 、ipv4 多种检测策略。

示例代码:

public class SensitiveWordQuickDemo {

    public static void main(String[] args) {
// 邮箱检测
String text1 = "楼主好人,邮箱 sensitiveword@xx.com";
List<String> emailWords = SensitiveWordBs.newInstance()
.enableEmailCheck(true)
.init()
.findAll(text1);
System.out.println("邮箱检测: " + emailWords); // 数字检测
String text2 = "你懂得:12345678";
List<String> numWords = SensitiveWordBs.newInstance()
.enableNumCheck(true)
.init()
.findAll(text2);
System.out.println("数字检测: " + numWords); // URL 检测
String text3 = "点击链接 https://www.baidu.com 查看答案,当然也可以是 baidu.com、www.baidu.com";
List<String> urlWords = SensitiveWordBs.newInstance()
.enableUrlCheck(true)
.wordCheckUrl(WordChecks.urlNoPrefix())
.init()
.findAll(text3);
System.out.println("URL 检测: " + urlWords); // IPv4 检测
String text4 = "个人网站,如果网址打不开可以访问 127.0.0.1。";
List<String> ipWords = SensitiveWordBs.newInstance()
.enableIpv4Check(true)
.init()
.findAll(text4);
System.out.println("IPv4 检测: " + ipWords);
} }

显示结果:

4 优雅 API

为了让使用更加优雅,统一使用 fluent-api 的方式定义。

用户可以使用 SensitiveWordBs 进行如下定义:

注意:配置后,要使用我们新定义的 SensitiveWordBs 的对象,而不是以前的工具方法。工具方法配置都是默认的。

public class AdvancedExample {

    public static void main(String[] args) {
SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
.ignoreCase(true)
.ignoreWidth(true)
.ignoreNumStyle(true)
.ignoreChineseStyle(true)
.ignoreEnglishStyle(true)
.ignoreRepeat(false)
.enableNumCheck(false)
.enableEmailCheck(false)
.enableUrlCheck(false)
.enableIpv4Check(false)
.enableWordCheck(true)
.wordFailFast(true)
.wordCheckNum(WordChecks.num())
.wordCheckEmail(WordChecks.email())
.wordCheckUrl(WordChecks.url())
.wordCheckIpv4(WordChecks.ipv4())
.wordCheckWord(WordChecks.word())
.numCheckLen(8)
.wordTag(WordTags.none())
.charIgnore(SensitiveWordCharIgnores.defaults())
.wordResultCondition(WordResultConditions.alwaysTrue())
.init(); final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
System.out.println(wordBs.contains(text));
System.out.println(wordBs.findFirst(text));
} }

5 定义词库

01 新增删除敏感词

初始化之后,sensitive-word 支持对单个词的新增/删除。

  • addWord(word) 新增敏感词,支持单个词/集合

  • removeWord(word) 删除敏感词,支持单个词/集合

示例代码:

final String text = "测试一下新增敏感词,验证一下删除和新增对不对";

SensitiveWordBs sensitiveWordBs =
SensitiveWordBs.newInstance()
.wordAllow(WordAllows.empty())
.wordDeny(WordDenys.empty())
.init(); // 当前
Assert.assertEquals("[]", sensitiveWordBs.findAll(text).toString()); // 新增单个
sensitiveWordBs.addWord("测试");
sensitiveWordBs.addWord("新增");
Assert.assertEquals("[测试, 新增, 新增]", sensitiveWordBs.findAll(text).toString()); // 删除单个
sensitiveWordBs.removeWord("新增");
Assert.assertEquals("[测试]", sensitiveWordBs.findAll(text).toString());
sensitiveWordBs.removeWord("测试");
Assert.assertEquals("[]", sensitiveWordBs.findAll(text).toString()); // 新增集合
sensitiveWordBs.addWord(Arrays.asList("新增", "测试"));
Assert.assertEquals("[测试, 新增, 新增]", sensitiveWordBs.findAll(text).toString());
// 删除集合
sensitiveWordBs.removeWord(Arrays.asList("新增", "测试"));
Assert.assertEquals("[]", sensitiveWordBs.findAll(text).toString()); // 新增数组
sensitiveWordBs.addWord("新增", "测试");
Assert.assertEquals("[测试, 新增, 新增]", sensitiveWordBs.findAll(text).toString());
// 删除集合
sensitiveWordBs.removeWord("新增", "测试");
Assert.assertEquals("[]", sensitiveWordBs.findAll(text).toString());

02 自定义词库来源(数据库 / 接口)

我们可以实现接口 IWordDeny 来扩展,例如从数据库取敏感词,实现自定义词库。

public class CustomDictionaryExample {

    public static void main(String[] args) {
SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
.wordDeny(new IWordDeny() {
@Override
public List<String> deny() {
// 这里可以从数据库查询
return Arrays.asList("勇哥", "敏感词A", "敏感词B");
}
})
.init(); System.out.println(wordBs.findAll("这是一个敏感词A 的测试"));
} }

6 Spring 整合

当我们需要在 SpringBoot 项目中使用敏感词过滤文本时,可以定义敏感词引导类。

示例见如下代码:

@Configuration
public class SpringSensitiveWordConfig { @Autowired
private MyDdWordAllow myDdWordAllow; @Autowired
private MyDdWordDeny myDdWordDeny; /**
* 初始化引导类
* @return 初始化引导类
* @since 1.0.0
*/
@Bean
public SensitiveWordBs sensitiveWordBs() {
SensitiveWordBs sensitiveWordBs = SensitiveWordBs.newInstance()
.wordAllow(WordAllows.chains(WordAllows.defaults(), myDdWordAllow))
.wordDeny(myDdWordDeny)
// 各种其他配置
.init(); return sensitiveWordBs;
} }

7 敏感词控制台

sensitive-word-admin 是和 sensitive-word 配套使用的控制台。

  • 前端采用Vue、Element UI。
  • 后端采用Spring Boot、Spring Security、Redis & Jwt。
  • 权限认证使用Jwt,支持多终端认证系统。
  • 支持加载动态权限菜单,多方式轻松权限控制。
  • 高效率开发,使用代码生成器可以一键生成前后端代码。

参考文章:

https://cloud.tencent.com/developer/news/1311331

sensitive-word:一个简单易用的敏感词过滤框架的更多相关文章

  1. 5分钟构建无服务器敏感词过滤后端系统(基于FunctionGraph)

    摘要:开发者通过函数工作流,无需配置和管理服务器,以无服务器的方式构建应用,便能开发出一个弹性高可用的后端系统.托管函数具备以毫秒级弹性伸缩.免运维.高可靠的方式运行,极大地提高了开发和运维效率,减小 ...

  2. 5分钟Serverless实践 | 构建无服务器的敏感词过滤后端系统

    前言 在上一篇“5分钟Serverless实践”系列文章中,我们介绍了什么是Serverless,以及如何构建一个无服务器的图片鉴黄Web应用,本文将延续这个话题,以敏感词过滤为例,介绍如何构建一个无 ...

  3. 8.2 前端检索的敏感词过滤的Python实现(针对元搜索)

    对于前端的搜索内容进行控制,比如敏感词过滤,同样使用socket,这里使用Python语言做一个demo.这里不得不感叹一句,socket真是太神奇了,可以跨语言把功能封装,为前端提供服务. 下面就是 ...

  4. 分享一个简单易用的RPC开源项目—Tatala

    http://zijan.iteye.com/blog/2041894 这个项目最早(2008年)是用于一个网络游戏的Cache Server,以及一个电子商务的Web Session服务.后来不断增 ...

  5. 一个简单易用的容器管理平台-Humpback

    什么是Humpback? 在回答这个问题前,我们得先了解下什么的 Docker(哦,现在叫 Moby,文中还是继续称 Docker). 在 Docker-百度百科 中,对 Docker 已经解释得很清 ...

  6. 分享一个简单易用的软件定时器模块(MultiTimer)——基于keil+stm32f103zet+hal库(裸机实现)

    公众号上看到一个比较好的一个github项目:https://github.com/0x1abin/MultiTimer 今天看了看,简单的,就移植了- 且看文档的说明, ============== ...

  7. C# 编写一个简单易用的 Windows 截屏增强工具

    半年前我开源了 DreamScene2 一个小而快并且功能强大的 Windows 动态桌面软件.有很多的人喜欢,这使我有了继续做开源的信心.这是我的第二个开源作品 ScreenshotEx 一个简单易 ...

  8. 用php实现一个敏感词过滤功能

    周末空余时间撸了一个敏感词过滤功能,下边记录下实现过程. 敏感词,一方面是你懂的,另一方面是我们自己可能也要过滤一些人身攻击或者广告信息等,具体词库可以google下,有很多. 过滤敏感词,使用简单的 ...

  9. java实现敏感词过滤(DFA算法)

    小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxo ...

  10. 浅析敏感词过滤算法(C++)

    为了提高查找效率,这里将敏感词用树形结构存储,每个节点有一个map成员,其映射关系为一个string对应一个TreeNode. STL::map是按照operator<比较判断元素是否相同,以及 ...

随机推荐

  1. 前端开发系列004-基础篇之JavaScript的字符串

    本文将重点介绍javaScript语言中字符串,操作字符串的常见方法以及具体的代码实现等. 一.字符串简单介绍 关于字符串(类型),其实在我的另一篇文章中 JavaScript语言基础已经有过下面这段 ...

  2. vs 代码格式化

    解决方案 ctrl + A: ctrl + K + F; 参考链接 (博客园大牛)[https://www.cnblogs.com/chenmingjun/p/8119029.html]

  3. 使用AssemblyScript在360浏览器下报错 SyntaxError: Unexpected reserved word

    背景 最近在一个项目中使用了AssemblyScript,它能将类似于TypeScript的代码编译为WebAssembly,在其他浏览器都能正常使用,然而在360浏览器上却会报错:SyntaxErr ...

  4. Win11双击文件夹卡死转圈打不开的问题

    有一部分雨林木风官网的win11专业版用户,在使用电脑鼠标双击文件夹时,出现无法打开,而且箭头也是一直在转圈圈的问题,这是个什么情况呢?本文中,雨林木风小编将为大家分享详细的解决方法,希望可以帮助到有 ...

  5. win11系统出现内部错误2203的问题

    有不少深度系统的win11专业版用户,在电脑上安装软件时提示2203的内部错误的问题,导致软件安装失败,这该如何解决呢?如果您也遇到这个问题不知道如何解决.就来看看深度技术小编整理的解决方案,希望有所 ...

  6. 2025年7月份实时最新获取地图边界数据方法,省市区县街道多级联动【文末附实时geoJson数据下载】

    动态生成最新行政区划 GeoJSON 数据并结合 ECharts 实现地图下钻功能 在开发基于地图的数据可视化应用时,一个常见的挑战是获取准确且最新的行政区划边界数据(GeoJSON).许多现有的在线 ...

  7. CF405E Graph Cutting 解题报告

    CF405E Graph Cutting 解题报告 1 题目链接 https://codeforces.com/problemset/problem/405/E 2 题目整理 题目 : 图形切割 题目 ...

  8. PGSQL 批量更新

    概述 在我们的平常业务中,经常需要批量更新数据,例如:现阶段需要更新 1000 个包裹的上网时间,每个包裹的上网时间是不一样的,假如我们一个一个包裹更新,则需要与数据库进行 1000 次的交互,很大的 ...

  9. 珂朵莉树(老司机树,ODT,颜色段均摊)

    前言 在宿舍里有人说珂朵莉树写起来比shi山线段树方便多了. 正文 珂朵莉树,又名老司机树,颜色段均摊,ODT. 可以在数据完全随机化的情况下较快的完成一些操作(所以容易被卡). 珂朵莉树其实形态并不 ...

  10. A - Expedition

    https://vjudge.net/contest/393971#overview http://poj.org/problem?id=2431 A group of cows grabbed a ...