敏感词过滤工具
java
import com.github.houbb.sensitive.word.api.IWordContext;
import com.github.houbb.sensitive.word.api.IWordReplace;
import com.github.houbb.sensitive.word.api.IWordResult;
import com.github.houbb.sensitive.word.utils.InnerWordCharUtils;
public class MyWordReplace implements IWordReplace {
@Override
public void replace(StringBuilder stringBuilder, char[] chars, IWordResult iWordResult, IWordContext iWordContext) {
// 根据字符数组和词结果信息构建敏感词字符串
String sensitiveWord = InnerWordCharUtils.getString(chars, iWordResult);
if ("五星红旗".equals(sensitiveWord)){
stringBuilder.append("国家旗帜");
} else if ("毛主席".equals(sensitiveWord)) {
stringBuilder.append("教员");
} else {
// 默认替换
int length =iWordResult.endIndex()-
敏感词过滤工具
一、简介
sensitive-word 基于 DFA 算法实现的高性能敏感词工具。
二、应用场景
-
社交媒体和论坛:在用户生成内容(UGC)平台上,如微博、微信、论坛等,敏感词过滤器用于筛查并阻止不当言论,包括辱骂、歧视性语言、色情内容、政治敏感词汇等。
-
在线游戏:游戏中聊天功能可能被玩家用于发送不当信息,敏感词过滤器可以防止这种行为,维护游戏环境的健康。
-
企业通信工具:如企业邮箱、即时消息软件等,过滤不恰当的语言,保持专业沟通环境。
-
新闻媒体和出版物:在发布前审查文章、评论,避免包含违规或敏感信息。
-
教育平台:确保在线课程讨论区、学生论坛等区域的内容适宜所有年龄层的学生。
-
招聘广告和简历筛选:自动识别并排除含有性别、种族或其他偏见的描述。
-
电商平台:监控商品标题、描述和用户评价中的敏感词汇,确保内容合规。
-
直播和视频平台:实时监控直播间的弹幕和评论,防止不良信息传播。
-
智能客服与机器人对话:确保AI与用户的互动中不会出现不当言论,维护品牌形象。
-
政府和公共部门:在新闻发布、政策公告等官方渠道中避免敏感词汇,维护社会稳定和谐。
三、使用方法
一、Maven引入
XML
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>sensitive-word</artifactId>
<version>0.18.0</version>
</dependency>
二、核心方法
SensitiveWordHelper
作为敏感词的工具类,核心方法如下:
方法 | 参数 | 返回值 | 说明 |
contains(String) | 待验证的字符串 | 布尔值 | 验证字符串是否包含敏感词 |
findFirst(String) | 待验证的字符串 | 字符串 | 返回字符串中第一个敏感词 |
findFirst(String, IWordResultHandler) | IWordResultHandler 结果处理类 | 字符串 | 返回字符串中第一个敏感词 |
findAll(String) | 待验证的字符串 | 字符串列表 | 返回字符串中所有敏感词 |
findAll(String, IWordResultHandler) | IWordResultHandler 结果处理类 | 字符串列表 | 返回字符串中所有敏感词 |
replace(String) | 使用 * 替换敏感词 |
字符串 | 返回脱敏后的字符串 |
replace(String, char) | 使用指定的 char 替换敏感词 | 字符串 | 返回脱敏后的字符串 |
replace(String, ISensitiveWordReplace) | 使用自定义替换策略替换敏感词 | 字符串 | 返回脱敏后的字符串 |
四、更多特性
后续的诸多特性,主要是针对各种针对各种情况的处理,尽可能的提升敏感词命中率。
这是一场漫长的攻防之战。
样式处理
忽略大小写
java
final String text = "fuCK the bad words.";
String word = SensitiveWordHelper.findFirst(text);
Assert.assertEquals("fuCK", word);
忽略半角圆角
java
final String text = "fuck the bad words.";
String word = SensitiveWordHelper.findFirst(text);
Assert.assertEquals("fuck", word);
忽略数字的写法
这里实现了数字常见形式的转换。
java
final String text = "这个是我的微信:9⓿二肆⁹₈③⑸⒋➃㈤㊄";
List<String> wordList = SensitiveWordBs.newInstance().enableNumCheck(true).init().findAll(text);
Assert.assertEquals("[9⓿二肆⁹₈③⑸⒋➃㈤㊄]", wordList.toString());
忽略繁简体
java
inal String text = "我爱我的祖国和五星紅旗。";
List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[五星紅旗]", wordList.toString());
忽略英文的书写格式
java
final String text = "Ⓕⓤc⒦ the bad words";
List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[Ⓕⓤc⒦]", wordList.toString());
忽略重复词
java
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());
更多检测策略
邮箱检测
邮箱等个人信息,默认未启用。
java
final String text = "楼主好人,邮箱 sensitiveword@xx.com";
List<String> wordList = SensitiveWordBs.newInstance().enableEmailCheck(true).init().findAll(text);
Assert.assertEquals("[sensitiveword@xx.com]", wordList.toString());
连续数字检测
一般用于过滤手机号/QQ等广告信息,默认未启用。
V0.2.1 之后,支持通过 numCheckLen(长度)
自定义检测的长度。
java
final String text = "你懂得:12345678";
// 默认检测 8 位
List<String> wordList = SensitiveWordBs.newInstance()
.enableNumCheck(true)
.init().findAll(text);
Assert.assertEquals("[12345678]", wordList.toString());
// 指定数字的长度,避免误杀
List<String> wordList2 = SensitiveWordBs.newInstance()
.enableNumCheck(true)
.numCheckLen(9)
.init()
.findAll(text);
Assert.assertEquals("[]", wordList2.toString());
网址检测
用于过滤常见的网址信息,默认未启用。
v0.18.0 优化 URL 检测,更加严格,降低误判率
java
final String text = "点击链接 https://www.baidu.com 查看答案";
final SensitiveWordBs sensitiveWordBs = SensitiveWordBs.newInstance().enableUrlCheck(true).init();
List<String> wordList = sensitiveWordBs.findAll(text);
Assert.assertEquals("[https://www.baidu.com]", wordList.toString());
Assert.assertEquals("点击链接 ********************* 查看答案", sensitiveWordBs.replace(text));
IPV4 检测
v0.17.0 支持
避免用户通过 ip 绕过网址检测等,默认未启用。
java
final String text = "个人网站,如果网址打不开可以访问 127.0.0.1。";
final SensitiveWordBs sensitiveWordBs = SensitiveWordBs.newInstance().enableIpv4Check(true).init();
List<String> wordList = sensitiveWordBs.findAll(text);
Assert.assertEquals("[127.0.0.1]", wordList.toString());
引导类特性配置
说明
上面的特性默认都是开启的,有时业务需要灵活定义相关的配置特性。
所以 v0.0.14 开放了属性配置。
配置方法
为了让使用更加优雅,统一使用 fluent-api 的方式定义。
用户可以使用 SensitiveWordBs
进行如下定义:
java
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)
.numCheckLen(8)
.wordTag(WordTags.none())
.charIgnore(SensitiveWordCharIgnores.defaults())
.wordResultCondition(WordResultConditions.alwaysTrue())
.init();
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
Assert.assertTrue(wordBs.contains(text));
配置说明
其中各项配置的说明如下:
序号 | 方法 | 说明 | 默认值 |
1 | ignoreCase | 忽略大小写 | true |
2 | ignoreWidth | 忽略半角圆角 | true |
3 | ignoreNumStyle | 忽略数字的写法 | true |
4 | ignoreChineseStyle | 忽略中文的书写格式 | true |
5 | ignoreEnglishStyle | 忽略英文的书写格式 | true |
6 | ignoreRepeat | 忽略重复词 | false |
7 | enableNumCheck | 是否启用数字检测。 | false |
8 | enableEmailCheck | 是有启用邮箱检测 | false |
9 | enableUrlCheck | 是否启用链接检测 | false |
10 | enableIpv4Check | 是否启用IPv4检测 | false |
11 | enableWordCheck | 是否启用敏感单词检测 | true |
12 | numCheckLen | 数字检测,自定义指定长度。 | 8 |
13 | wordTag | 词对应的标签 | none |
14 | charIgnore | 忽略的字符 | none |
15 | wordResultCondition | 针对匹配的敏感词额外加工,比如可以限制英文单词必须全匹配 | 恒为真 |
核心方法及部分更多特性代码如下:
java
import com.github.houbb.sensitive.word.api.IWordReplace;
import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.github.houbb.sensitive.word.support.ignore.SensitiveWordCharIgnores;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest(classes = SensitiveWordTests.class)
public class SensitiveWordTests {
@Test
//检测是否包含敏感词
public void containsTest() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
boolean contains = SensitiveWordHelper.contains(text);
System.out.println(contains);
}
@Test
//查找第一个敏感词
public void findFirstTest() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
String word = SensitiveWordHelper.findFirst(text);
System.out.println("返回第一个敏感词:"+word);
}
@Test
//查找所有敏感词
public void findAllTest() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
List<String> wordList = SensitiveWordHelper.findAll(text);
System.out.println("返回所有敏感词:"+wordList.toString());
}
@Test
//默认替换策略,替换敏感词
public void replaceTest() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
String replace = SensitiveWordHelper.replace(text);
System.out.println("替换敏感词:"+replace);
}
@Test
//自定义替换字符,替换敏感词
public void replaceCharTest() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
String result = SensitiveWordHelper.replace(text, '0');
System.out.println("替换敏感词:"+result);
}
@Test
//自定义替换策略,替换敏感词
public void replaceTest1() {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
IWordReplace replace = new MyWordReplace();
String result = SensitiveWordHelper.replace(text, replace);
System.out.println("替换敏感词:"+result);
}
@Test
//忽略大小写
public void ignoreCaseTest() {
final String text = "fuCK the bad words.";
String word = SensitiveWordHelper.findFirst(text);
System.out.println("忽略大小写:"+word);
String replace = SensitiveWordHelper.replace(text);
System.out.println("忽略大小写:"+replace);
}
@Test
//忽略半角圆角
public void ignoreWidthTest() {
final String text = "fuck ①Ⓕⓤc⒦ the bad words.";
String word = SensitiveWordHelper.replace(text);
System.out.println("忽略半角圆角:"+word);
}
//邮箱、连续数字、网址 默认不开启 需要手动开启
@Test
//过滤邮箱
public void test() {
String text= "邮箱 sensitiveword@xx.com";
String replace = SensitiveWordBs.newInstance().enableEmailCheck(true).init().replace(text);
System.out.println(replace);
}
@Test
//过滤电话
public void test1() {
String text= "电话 12345678901";
String replace = SensitiveWordBs.newInstance()
.enableNumCheck(true)
.numCheckLen(12)//指定数字长度
.init().replace(text);
System.out.println(replace);
}
@Test
//过滤网址
public void test3(){
String text= "请访问我们的官方网站:https://example.com";
String replace = SensitiveWordBs.newInstance().enableUrlCheck(true).init().replace(text);
System.out.println(replace);
}
@Test
//过滤时中间有特殊字符,无法过滤
public void test4(){
final String text = "傻@冒,狗+东西,1212";
// String replace = SensitiveWordHelper.replace(text);
// System.out.println(replace);
String replace = SensitiveWordBs.newInstance()
.charIgnore(SensitiveWordCharIgnores.specialChars())
.init()
.replace(text);
System.out.println(replace);
}
@Test
//复杂语句
public void test5(){
final String text = "傻@冒,狗+东西,1212邮箱 sensitiveword@xx.com请访问我们的官方网站:https://example.com电话 12345678901fuck ①Ⓕⓤc⒦ the bad words.";
//配置所需的方法 忽略大小写、忽略半角圆角、忽略英文样式、忽略数字、忽略邮箱、忽略网址、忽略电话
String replace = SensitiveWordBs.newInstance()
.charIgnore(SensitiveWordCharIgnores.specialChars())
.ignoreEnglishStyle(true)
.enableEmailCheck(true)
.init()
.replace(text);
System.out.println(replace);
}
}
自定义敏感词替换策略中的MyWordReplace代码如下:
java
package com.beiyou;
iWordResult.startIndex();
for (int i = 0; i < length; i++) {
stringBuilder.append('*');
}
}
}
}
如果还有问题可以点击下面网址(可能会打不开,多尝试几次)