Skip to content

👮‍♂️The sensitive word tool for java.(基于 DFA 算法实现的高性能 java 敏感词工具框架。请勿发布涉及政治、广告、营销、翻墙、违反国家法律法规等内容。)

License

Notifications You must be signed in to change notification settings

alant77/sensitive-word

 
 

Repository files navigation

sensitive-word

sensitive-word 基于 DFA 算法实现的高性能敏感词工具。

Maven Central Open Source Love

创作目的

实现一款好用敏感词工具。

基于 DFA 算法实现,目前敏感词库内容收录 6W+(源文件 18W+,经过一次删减)。

后期将进行持续优化和补充敏感词库,并进一步提升算法的性能。

希望可以细化敏感词的分类,感觉工作量比较大,暂时没有进行。

特性

  • 6W+ 词库,且不断优化更新

  • 基于 DFA 算法,性能较好

  • 基于 fluent-api 实现,使用优雅简洁

  • 支持敏感词的判断、返回、脱敏等常见操作

  • 支持全角半角互换

  • 支持英文大小写互换

  • 支持数字常见形式的互换

  • 支持中文繁简体互换

  • 支持英文常见形式的互换

  • 支持用户自定义敏感词和白名单

变更日志

CHANGE_LOG.md

快速开始

准备

  • JDK1.7+

  • Maven 3.x+

Maven 引入

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

api 概览

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

方法 参数 返回值 说明
contains(String) 待验证的字符串 布尔值 验证字符串是否包含敏感词
findAll(String) 待验证的字符串 字符串列表 返回字符串中所有敏感词
replace(String, char) 使用指定的 char 替换敏感词 字符串 返回脱敏后的字符串
replace(String) 使用 * 替换敏感词 字符串 返回脱敏后的字符串

使用实例

所有测试案例参见 SensitiveWordHelperTest

判断是否包含敏感词

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";

Assert.assertTrue(SensitiveWordHelper.contains(text));

返回第一个敏感词

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";

String word = SensitiveWordHelper.findFirst(text);
Assert.assertEquals("五星红旗", word);

返回所有敏感词

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";

List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[五星红旗, 毛主席, 天安门]", wordList.toString());

默认的替换策略

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
String result = SensitiveWordHelper.replace(text);
Assert.assertEquals("****迎风飘扬,***的画像屹立在***前。", result);

指定替换的内容

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
String result = SensitiveWordHelper.replace(text, '0');
Assert.assertEquals("0000迎风飘扬,000的画像屹立在000前。", result);

更多特性

后续的诸多特性,主要是针对各种针对各种情况的处理,尽可能的提升敏感词命中率。

这是一场漫长的攻防之战。

忽略大小写

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

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

忽略半角圆角

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

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

忽略数字的写法

这里实现了数字常见形式的转换。

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

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

忽略繁简体

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

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

忽略英文的书写格式

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

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

忽略重复词

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

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

邮箱检测

final String text = "楼主好人,邮箱 [email protected]";

List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[[email protected]]", wordList.toString());

特性配置

说明

上面的特性默认都是开启的,有时业务需要灵活定义相关的配置特性。

所以 v0.0.14 开放了属性配置。

配置方法

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

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

SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
        .ignoreCase(true)
        .ignoreWidth(true)
        .ignoreNumStyle(true)
        .ignoreChineseStyle(true)
        .ignoreEnglishStyle(true)
        .ignoreRepeat(true)
        .init();

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
Assert.assertTrue(wordBs.contains(text));

配置说明

其中各项配置的说明如下:

序号 方法 说明
1 ignoreCase 忽略大小写
2 ignoreWidth 忽略半角圆角
3 ignoreNumStyle 忽略数字的写法
4 ignoreChineseStyle 忽略中文的书写格式
5 ignoreEnglishStyle 忽略英文的书写格式
6 ignoreRepeat 忽略重复词

用户自定义

敏感词和白名单

直接在 resource 目录下新建文件,每一行对应一个敏感词。

sensitive_word_deny.txt 代表用户自定义敏感词文件。

sensitive_word_allow.txt 代表用户自定义白名单文件。

测试

我们在敏感词文件中加入一行,内容为 自定义敏感词,同时在白名单文件中加入一行, 内容为 gender 作为用户不认为是敏感词的信息。

  • 测试代码
final String text = "gender 我们认为应该通过,自定义敏感词我们认为应该拒绝。";

List<String> wordList = SensitiveWordHelper.findAll(text);
Assert.assertEquals("[自定义敏感词]", wordList.toString());

动态加载

情景说明

有时候我们希望将敏感词的加载设计成动态的,比如控台修改,然后可以实时生效。

v0.0.13 支持了这种特性。

接口说明

为了实现这个特性,并且兼容以前的功能,我们定义了两个接口。

IWordDeny

接口如下,可以自定义自己的实现。

/**
 * 拒绝出现的数据-返回的内容被当做是敏感词
 * @author binbin.hou
 * @since 0.0.13
 */
public interface IWordDeny {

    /**
     * 获取结果
     * @return 结果
     * @since 0.0.13
     */
    List<String> deny();

}

IWordAllow

接口如下,可以自定义自己的实现。

/**
 * 允许的内容-返回的内容不被当做敏感词
 * @author binbin.hou
 * @since 0.0.13
 */
public interface IWordAllow {

    /**
     * 获取结果
     * @return 结果
     * @since 0.0.13
     */
    List<String> allow();

}

配置使用

为了让使用更加优雅,我们设计了引导类 SensitiveWordBs

可以通过 wordDeny() 指定敏感词,wordAllow() 指定非敏感词,通过 init() 初始化敏感词字典。

SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
        .wordDeny(WordDenys.system())
        .wordAllow(WordAllows.system())
        .init();

final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
Assert.assertTrue(wordBs.contains(text));

备注:init() 对于敏感词 DFA 的构建是比较耗时的,一般建议在应用初始化的时候只初始化一次。而不是重复初始化!

后期 road-map

  • 停顿词

  • 同音字处理

  • 形近字处理

  • 文字镜像翻转

  • 文字降噪处理

  • 敏感词标签支持

  • 邮箱后缀检测

拓展阅读

敏感词工具实现思路

DFA 算法讲解

敏感词库优化流程

停止词的思考记录

About

👮‍♂️The sensitive word tool for java.(基于 DFA 算法实现的高性能 java 敏感词工具框架。请勿发布涉及政治、广告、营销、翻墙、违反国家法律法规等内容。)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 95.1%
  • Shell 3.5%
  • Batchfile 1.4%