민감한 단어는 DFA 알고리즘을 기반으로 한 고성능 민감한 단어 도구입니다.
온라인 경험
어렵고 복잡한 질병이있는 경우 : 기술 교환 그룹에 가입 할 수 있습니다.
민감한 단어 아민은 해당 콘솔 애플리케이션입니다. 기능은 현재 개발 초기 단계에 있으며 MVP 버전을 사용할 수 있습니다.
안녕하세요 여러분, 저는 Lao Ma입니다.
나는 항상 간단하고 사용하기 쉬운 민감한 단어 도구를 구현하고 싶었 으므로이 도구 오픈 소스를 구현했습니다.
DFA 알고리즘 구현을 기반으로, 민감한 동의어 사전의 내용에는 현재 6W+ (하나의 삭제 후 소스 파일 18W+)가 포함됩니다.
후반에는 민감한 시소러스가 지속적으로 최적화되고 보충 될 것이며 알고리즘의 성능이 더욱 향상됩니다.
v0.24.0은 민감한 단어의 분류 및 개선을 지원하기 시작했지만 작업량은 비교적 크기 때문에 필연적으로 누락이 있습니다.
PR 개선, GitHub 요청에 오신 것을 환영합니다. 또는 기술 교환 그룹에 가입하여 의사 소통하고 자랑하십시오!
6W+ 시소러스 및 지속적인 최적화 및 업데이트
유창한 -API 구현, 우아하고 간결한 사용을 기반으로합니다
DFA 알고리즘을 기반으로 성능은 7W+ QPS이며 응용 프로그램은 무의미합니다.
민감한 단어의 판단, 귀환 및 탈감작과 같은 일반적인 작업을 지원합니다.
일반적인 형식 변환을 지원합니다
전폭 반 폭 인터체인지, 영어 사례 교환, 일반적인 형태의 숫자, 중국 전통 및 단순화 된 중국어, 일반적인 형태의 영어 교환, 중복 단어 무시 등
민감한 단어 탐지, 이메일 탐지, 디지털 탐지, 웹 사이트 탐지, IPv4 등을 지원합니다.
맞춤형 교체 정책을 지원합니다
사용자 정의 민감한 단어 및 화이트리스트를 지원합니다
실시간으로 유효한 동적 데이터 업데이트 (사용자 사용자 정의)를 지원합니다.
민감한 단어에 대한 태그 인터페이스 + 내장 분류 구현 지원
더 유연하게 일치하는 특수 캐릭터를 건너 뛰는 지원
전체 초기화없이 흑백 목록의 단일 추가/수정을 지원합니다.
change_log.md
때로는 민감한 단어에 대한 콘솔이있어보다 유연하고 편리합니다.
상자에서 민감한 워드 콘솔 서비스를 구현하는 방법은 무엇입니까?
많은 민감한 단어 태그 파일이 정렬되어 민감한 단어를보다 편리하게 만들 수 있습니다.
이 두 자료는 아래 기사에서 읽을 수 있습니다.
V0.11.0 민감한 단어 및 해당 태그 파일의 새로운 기능
현재 V0.24.0에는 내장 된 단어 태그가 있으며 필요한 경우 최신 버전으로 업그레이드하는 것이 좋습니다.
오픈 소스는 쉽지 않습니다. 이 프로젝트가 도움이된다면 Lao Ma를 초대하여 우유 차 한 잔을 마실 수 있습니다.

JDK1.8+
Maven 3.x+
< dependency >
< groupId >com.github.houbb</ groupId >
< artifactId >sensitive-word</ artifactId >
< version >0.24.0</ version >
</ dependency > SensitiveWordHelper 민감한 단어를위한 도구 클래스입니다. 핵심 방법은 다음과 같습니다.
참고 : SensitiveWordHelper 기본 구성을 제공합니다. 유연한 사용자 정의 구성을 만들려면 부팅 클래스 기능 구성을 참조하십시오.
| 방법 | 매개 변수 | 반환 값 | 설명 |
|---|---|---|---|
| 포함 (문자열) | 확인할 문자열 | 부울 가치 | 문자열에 민감한 단어가 포함되어 있는지 확인하십시오 |
| 교체 (String, Isensitivewordreplace) | 민감한 단어를 지정된 대체 전략으로 바꾸십시오 | 끈 | 탈감작 된 문자열을 반환합니다 |
| 교체 (String, char) | 지정된 숯을 사용하여 민감한 단어를 대체하십시오 | 끈 | 탈감작 된 문자열을 반환합니다 |
| 대체 (문자열) | 민감한 단어를 대체하려면 * 사용하십시오 | 끈 | 탈감작 된 문자열을 반환합니다 |
| findall (문자열) | 확인할 문자열 | 문자열 목록 | 문자열에서 모든 민감한 단어를 반환합니다 |
| FindFirst (String) | 확인할 문자열 | 끈 | 문자열에서 첫 번째 민감한 단어를 반환합니다 |
| findall (String, iwordresulthandler) | iWordresulthandler 결과 처리 클래스 | 문자열 목록 | 문자열에서 모든 민감한 단어를 반환합니다 |
| findfirst (String, iwordresulthandler) | iWordresulthandler 결과 처리 클래스 | 끈 | 문자열에서 첫 번째 민감한 단어를 반환합니다 |
| 태그 (문자열) | 민감한 단어에 대한 태그를 얻으십시오 | 민감한 단어 문자열 | 민감한 단어에 대한 태그 목록으로 돌아갑니다 |
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
Assert . assertTrue ( SensitiveWordHelper . contains ( text )); final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
String word = SensitiveWordHelper . findFirst ( text );
Assert . assertEquals ( "五星红旗" , word );CintitiveWordHelper.FindFirst (텍스트)는 다음과 같습니다.
String word = SensitiveWordHelper . findFirst ( text , WordResultHandlers . word ()); final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
List < String > wordList = SensitiveWordHelper . findAll ( text );
Assert . assertEquals ( "[五星红旗, 毛主席, 天安门]" , wordList . toString ());모든 민감한 단어 사용은 inritiveWordHelper.FindFirst ()와 유사하며 결과 처리 클래스 지정도 지원합니다.
CintitiveWordHelper.findall (텍스트)은 다음과 같습니다.
List < String > wordList = SensitiveWordHelper . findAll ( text , WordResultHandlers . word ());Wordresulthandlers.raw ()는 해당 첨자 정보 및 범주 정보를 유지할 수 있습니다.
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
// 默认敏感词标签为空
List < WordTagsDto > wordList1 = SensitiveWordHelper . findAll ( text , WordResultHandlers . wordTags ());
Assert . assertEquals ( "[WordTagsDto{word='五星红旗', tags=[]}, WordTagsDto{word='毛主席', tags=[]}, WordTagsDto{word='天安门', tags=[]}]" , wordList1 . 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 );v0.2.0은이 기능을 지원합니다.
장면 설명 : 때로는 다른 민감한 단어가 다른 대체 결과를 갖기를 원합니다. 예를 들어, [게임]은 [e-sports]로 대체되며 [실업]은 [Flexible Employment]로 대체됩니다.
물론 정기적 인 문자열 교체를 미리 사용해도 괜찮지 만 성능은 평균입니다.
사용의 예 :
/**
* 自定替换策略
* @since 0.2.0
*/
@ Test
public void defineReplaceTest () {
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
ISensitiveWordReplace replace = new MySensitiveWordReplace ();
String result = SensitiveWordHelper . replace ( text , replace );
Assert . assertEquals ( "国家旗帜迎风飘扬,教员的画像屹立在***前。" , result );
} 그중에서도 MySensitiveWordReplace 는 맞춤형 대체 정책이 있으며 다음과 같이 구현됩니다.
public class MyWordReplace implements IWordReplace {
@ Override
public void replace ( StringBuilder stringBuilder , final char [] rawChars , IWordResult wordResult , IWordContext wordContext ) {
String sensitiveWord = InnerWordCharUtils . getString ( rawChars , wordResult );
// 自定义不同的敏感词替换策略,可以从数据库等地方读取
if ( "五星红旗" . equals ( sensitiveWord )) {
stringBuilder . append ( "国家旗帜" );
} else if ( "毛主席" . equals ( sensitiveWord )) {
stringBuilder . append ( "教员" );
} else {
// 其他默认使用 * 代替
int wordLength = wordResult . endIndex () - wordResult . startIndex ();
for ( int i = 0 ; i < wordLength ; i ++) {
stringBuilder . append ( '*' );
}
}
}
} 우리는 일부 단어에 대해 고정 매핑을하고 다른 단어는 기본적으로 * 로 변환됩니다.
iWordresulthandler는 민감한 단어의 결과를 처리하고 사용자가 사용자 정의 할 수 있습니다.
내장 구현은 WordResultHandlers 도구 클래스를 참조하십시오.
민감한 단어 만 보존됩니다.
민감한 단어의 시작 및 끝 위시를 포함하여 민감한 단어와 관련된 정보를 유지합니다.
동시에, 단어와 해당 단어 레이블 정보가 유지됩니다.
모든 테스트 사례에 대해서는 민감한 단어를 참조하십시오
1) 기본 예
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
List < String > wordList = SensitiveWordHelper . findAll ( text );
Assert . assertEquals ( "[五星红旗, 毛主席, 天安门]" , wordList . toString ());
List < String > wordList2 = SensitiveWordHelper . findAll ( text , WordResultHandlers . word ());
Assert . assertEquals ( "[五星红旗, 毛主席, 天安门]" , wordList2 . toString ());
List < IWordResult > wordList3 = SensitiveWordHelper . findAll ( text , WordResultHandlers . raw ());
Assert . assertEquals ( "[WordResult{startIndex=0, endIndex=4}, WordResult{startIndex=9, endIndex=12}, WordResult{startIndex=18, endIndex=21}]" , wordList3 . toString ()); dict_tag_test.txt 파일에 해당 단어의 태그 정보를 지정합니다.
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
// 默认敏感词标签为空
List < WordTagsDto > wordList1 = SensitiveWordHelper . findAll ( text , WordResultHandlers . wordTags ());
Assert . assertEquals ( "[WordTagsDto{word='五星红旗', tags=[]}, WordTagsDto{word='毛主席', tags=[]}, WordTagsDto{word='天安门', tags=[]}]" , wordList1 . toString ());
List < WordTagsDto > wordList2 = SensitiveWordBs . newInstance ()
. wordTag ( WordTags . file ( "dict_tag_test.txt" ))
. init ()
. findAll ( text , WordResultHandlers . wordTags ());
Assert . assertEquals ( "[WordTagsDto{word='五星红旗', tags=[政治, 国家]}, WordTagsDto{word='毛主席', tags=[政治, 伟人, 国家]}, WordTagsDto{word='天安门', tags=[政治, 国家, 地址]}]" , wordList2 . toString ());후속 기능은 주로 민감한 단어의 적중률을 최대한 개선하기 위해 다양한 상황을 목표로하는 다양한 처리를 목표로합니다.
이것은 범죄와 방어의 긴 전투입니다.
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 = SensitiveWordBs . newInstance (). enableNumCheck ( true ). init (). 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 = SensitiveWordBs . newInstance ()
. ignoreRepeat ( true )
. init ()
. findAll ( text );
Assert . assertEquals ( "[ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦]" , wordList . toString ());이메일 주소와 같은 개인 정보는 기본적으로 활성화되지 않습니다.
final String text = "楼主好人,邮箱 [email protected]" ;
List < String > wordList = SensitiveWordBs . newInstance (). enableEmailCheck ( true ). init (). findAll ( text );
Assert . assertEquals ( "[[email protected]]" , wordList . toString ());일반적으로 휴대폰 번호/QQ와 같은 광고 정보를 필터링하는 데 사용되며 기본적으로 활성화되지 않습니다.
V0.2.1 후, numCheckLen(长度) 에 의해 감지 된 길이가 지원됩니다.
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 ());기본적으로 활성화되지 않은 공통 URL 정보를 필터링하는 데 사용됩니다.
v0.18.0 URL 감지 최적화, 이는 더 엄격하고 잘못 판단 속도를 줄입니다.
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 ));V0.17.0 지원
기본적으로 활성화되지 않은 IP 등을 통해 URL 감지를 우회하지 않도록하십시오.
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 사용하여 다음과 같이 정의 할 수 있습니다.
참고 : 구성 후 이전 공구 방법 대신 새롭게 정의 된 SensitiveWordBs 객체를 사용하십시오. 도구 메소드 구성이 모두 기본값입니다.
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 | 무지 | 사건을 무시하십시오 | 진실 |
| 2 | 무시된다 | 반 코너 둥근 모서리를 무시하십시오 | 진실 |
| 3 | 무시하십시오 | 숫자의 글을 무시하십시오 | 진실 |
| 4 | Chinesestyle을 무시하십시오 | 중국 작문 형식을 무시합니다 | 진실 |
| 5 | 무시하십시오 | 영어 작문 형식을 무시하십시오 | 진실 |
| 6 | 무시하십시오 | 중복 단어를 무시하십시오 | 거짓 |
| 7 | enableNumCheck | 디지털 감지 가능 여부. | 거짓 |
| 8 | enableAmailCheck | 이메일 감지가 활성화되어 있습니다 | 거짓 |
| 9 | ENABLEURLCHECK | 링크 감지 활성화 여부 | 거짓 |
| 10 | enableipv4check | IPv4 감지 가능 여부 | 거짓 |
| 11 | enablewordCheck | 민감한 단어 감지를 가능하게하는지 여부 | 진실 |
| 12 | Numchecklen | 디지털 감지, 지정된 길이를 사용자 정의합니다. | 8 |
| 13 | Wordtag | 해당 단어의 태그 | 없음 |
| 14 | Charignore | 캐릭터를 무시했습니다 | 없음 |
| 15 | WordresultCondition | 영어 단어의 전체 일치 요구를 제한하는 것과 같은 민감한 단어를 일치시키기위한 추가 처리 | 항상 사실입니다 |
v0.16.1이 지원됩니다. 때때로 우리는 메모리를 확보해야합니다.
메모리 재활용 문제에 대해
SensitiveWordBs wordBs = SensitiveWordBs . newInstance ()
. init ();
// 后续因为一些原因移除了对应信息,希望释放内存。
wordBs . destroy ();사용 시나리오 : 초기화 후 하나의 단어를 완전히 재구성하는 대신 단일 단어를 추가/삭제하려고합니다. 이 기능은 이것을 위해 준비되어 있습니다.
지원되는 버전 : v0.19.0
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 ());사용 시나리오 : 초기화 후 하나의 단어를 완전히 재구성하는 대신 단일 단어를 추가/삭제하려고합니다. 이 기능은 이것을 위해 준비되어 있습니다.
지원되는 버전 : v0.21.0
addWordAllow(word) 새로운 화이트리스트를 추가하고 단일 단어/컬렉션을 지원합니다
removeWordAllow(word) 화이트리스트를 제거하고 단일 단어/컬렉션을 지원합니다
final String text = "测试一下新增敏感词白名单,验证一下删除和新增对不对" ;
SensitiveWordBs sensitiveWordBs =
SensitiveWordBs . newInstance ()
. wordAllow ( WordAllows . empty ())
. wordDeny ( new IWordDeny () {
@ Override
public List < String > deny () {
return Arrays . asList ( "测试" , "新增" );
}
})
. init ();
// 当前
Assert . assertEquals ( "[测试, 新增, 新增]" , sensitiveWordBs . findAll ( text ). toString ());
// 新增单个
sensitiveWordBs . addWordAllow ( "测试" );
sensitiveWordBs . addWordAllow ( "新增" );
Assert . assertEquals ( "[]" , sensitiveWordBs . findAll ( text ). toString ());
// 删除单个
sensitiveWordBs . removeWordAllow ( "测试" );
Assert . assertEquals ( "[测试]" , sensitiveWordBs . findAll ( text ). toString ());
sensitiveWordBs . removeWordAllow ( "新增" );
Assert . assertEquals ( "[测试, 新增, 新增]" , sensitiveWordBs . findAll ( text ). toString ());
// 新增集合
sensitiveWordBs . addWordAllow ( Arrays . asList ( "新增" , "测试" ));
Assert . assertEquals ( "[]" , sensitiveWordBs . findAll ( text ). toString ());
// 删除集合
sensitiveWordBs . removeWordAllow ( Arrays . asList ( "新增" , "测试" ));
Assert . assertEquals ( "[测试, 新增, 新增]" , sensitiveWordBs . findAll ( text ). toString ());
// 新增数组
sensitiveWordBs . addWordAllow ( "新增" , "测试" );
Assert . assertEquals ( "[]" , sensitiveWordBs . findAll ( text ). toString ());
// 删除集合
sensitiveWordBs . removeWordAllow ( "新增" , "测试" );
Assert . assertEquals ( "[测试, 新增, 新增]" , sensitiveWordBs . findAll ( text ). toString ());이 방법은 버려졌습니다 . 전체 로딩을 피하기 위해 위의 증분 추가 방법을 사용하는 것이 좋습니다. 호환성을 위해이 방법은 여전히 남아 있습니다.
사용 방법 : sensitiveWordBs.init() 호출 할 때 iworddeny+iwordallow를 기반으로 민감한 어휘를 재구성하십시오. 초기화는 오랜 시간이 걸릴 수 있으므로 (2 단계), INT에 대한 모든 최적화는 완료되지 않은 경우 이전 어휘 기능에 영향을 미치지 않으며, 완료 후 새로운 기능이 우선합니다 .
@ Component
public class SensitiveWordService {
@ Autowired
private SensitiveWordBs sensitiveWordBs ;
/**
* 更新词库
*
* 每次数据库的信息发生变化之后,首先调用更新数据库敏感词库的方法。
* 如果需要生效,则调用这个方法。
*
* 说明:重新初始化不影响旧的方法使用。初始化完成后,会以新的为准。
*/
public void refresh () {
// 每次数据库的信息发生变化之后,首先调用更新数据库敏感词库的方法,然后调用这个方法。
sensitiveWordBs . init ();
}
} 위에서 언급했듯이 sensitiveWordBs.init(); 데이터베이스 사전이 변경되고 데이터베이스가 적용되어야합니다.
다른 용도는 앱을 다시 시작하지 않고 동일하게 유지됩니다.
지원되는 버전 : v0.13.0
때때로 우리는 [AV]를 민감한 단어로 정의하지만 일치하는 민감한 단어를 더 제한하고 싶을 수도 있지만, 우리는 [AV]를 일치시키기를 원하지 않습니다.
WordresultCondition 인터페이스를 사용자 정의하고 고유 한 정책을 구현할 수 있습니다.
WordResultConditions#alwaysTrue() 의 내장 정책은 항상 사실이며 WordResultConditions#englishWordMatch() 영어가 전체 단어와 일치해야합니다.
WordresultConditions 도구 클래스는 일치하는 정책을 얻을 수 있습니다
| 성취하다 | 설명 | 지원되는 버전 |
|---|---|---|
| 항상 트루 | 항상 사실입니다 | |
| EnglishWordMatch | 영어 단어 전체 단어 일치 | v0.13.0 |
| EnglishWordNumMatch | 영어 단어/번호 전체 단어 일치 | v0.20.0 |
| WordTags | [광고] 태그에만 초점을 맞추는 것과 같이 특정 태그를 만족시키는 사람들 | v0.23.0 |
| 체인 (iwordresultCondition ... 조건) | 여러 조건을 지정하고 동시에 만족시키는 지원 | v0.23.0 |
원래 기본 상황 :
final String text = "I have a nice day。" ;
List < String > wordList = SensitiveWordBs . newInstance ()
. wordDeny ( new IWordDeny () {
@ Override
public List < String > deny () {
return Collections . singletonList ( "av" );
}
})
. wordResultCondition ( WordResultConditions . alwaysTrue ())
. init ()
. findAll ( text );
Assert . assertEquals ( "[av]" , wordList . toString ());영어가 전체 단어와 일치해야한다고 지정할 수 있습니다.
final String text = "I have a nice day。" ;
List < String > wordList = SensitiveWordBs . newInstance ()
. wordDeny ( new IWordDeny () {
@ Override
public List < String > deny () {
return Collections . singletonList ( "av" );
}
})
. wordResultCondition ( WordResultConditions . englishWordMatch ())
. init ()
. findAll ( text );
Assert . assertEquals ( "[]" , wordList . toString ());물론 필요에 따라 더 복잡한 전략을 구현할 수 있습니다.
지원되는 버전 : v0.23.0
특정 레이블과 관련된 민감한 단어 만 반환 할 수 있습니다.
우리는 두 가지 민감한 단어를 지정했습니다 : 제품, av
MyWordTag는 우리가 정의하는 민감한 단어 태그 구현입니다.
/**
* 自定义单词标签
* @since 0.23.0
*/
public class MyWordTag extends AbstractWordTag {
private static Map < String , Set < String >> dataMap ;
static {
dataMap = new HashMap <>();
dataMap . put ( "商品" , buildSet ( "广告" , "中文" ));
dataMap . put ( "AV" , buildSet ( "色情" , "单词" , "英文" ));
}
private static Set < String > buildSet ( String ... tags ) {
Set < String > set = new HashSet <>();
for ( String tag : tags ) {
set . add ( tag );
}
return set ;
}
@ Override
protected Set < String > doGetTag ( String word ) {
return dataMap . get ( word );
}
}예를 들어, 각각의 다른 단어 태그에 중점을 둔 두 가지 구현 클래스를 시뮬레이션합니다.
// 只关心SE情
SensitiveWordBs sensitiveWordBsYellow = SensitiveWordBs . newInstance ()
. wordDeny ( new IWordDeny () {
@ Override
public List < String > deny () {
return Arrays . asList ( "商品" , "AV" );
}
})
. wordAllow ( WordAllows . empty ())
. wordTag ( new MyWordTag ())
. wordResultCondition ( WordResultConditions . wordTags ( Arrays . asList ( "色情" )))
. init ();
// 只关心广告
SensitiveWordBs sensitiveWordBsAd = SensitiveWordBs . newInstance ()
. wordDeny ( new IWordDeny () {
@ Override
public List < String > deny () {
return Arrays . asList ( "商品" , "AV" );
}
})
. wordAllow ( WordAllows . empty ())
. wordTag ( new MyWordTag ())
. wordResultCondition ( WordResultConditions . wordTags ( Arrays . asList ( "广告" )))
. init ();
final String text = "这些 AV 商品什么价格?" ;
Assert . assertEquals ( "[AV]" , sensitiveWordBsYellow . findAll ( text ). toString ());
Assert . assertEquals ( "[商品]" , sensitiveWordBsAd . findAll ( text ). toString ());우리의 민감한 단어는 일반적으로 [바보 모자]와 같은 연속적입니다.
그런 다음 [Silly! @#$ hat] 감지를 건너 뛰기 위해서는 욕설의 공격력이 줄어들지 않습니다.
그렇다면 이러한 유사한 시나리오를 처리하는 방법은 무엇입니까?
특수 문자 건너 뛰기 세트를 지정 하고이 의미없는 캐릭터를 무시할 수 있습니다.
V0.11.0은 지원을 시작합니다
Charignore에 해당하는 문자 전략은 사용자가 유연하게 정의 할 수 있습니다.
final String text = "傻@冒,狗+东西" ;
//默认因为有特殊字符分割,无法识别
List < String > wordList = SensitiveWordBs . newInstance (). init (). findAll ( text );
Assert . assertEquals ( "[]" , wordList . toString ());
// 指定忽略的字符策略,可自行实现。
List < String > wordList2 = SensitiveWordBs . newInstance ()
. charIgnore ( SensitiveWordCharIgnores . specialChars ())
. init ()
. findAll ( text );
Assert . assertEquals ( "[傻@冒, 狗+东西]" , wordList2 . toString ());때때로 우리는 사회적 상황, 폭력 등과 같은 민감한 단어에 분류 된 레이블을 추가하고 싶습니다.
이러한 방식으로 라벨 등에 따라 특정 유형의 레이블을 처리하는 것과 같은 더 많은 특성을 수행 할 수 있습니다.
지원되는 버전 : v0.10.0
주요 기능 지원 버전 : v0.24.0
이것은 단지 추상 인터페이스 일 뿐이며 사용자는 구현을 스스로 정의 할 수 있습니다. 예를 들어, 데이터베이스 쿼리, 파일 읽기, API 통화 등에서.
public interface IWordTag {
/**
* 查询标签列表
* @param word 脏词
* @return 结果
*/
Set < String > getTag ( String word );
} 대부분의 상황에서 사용을 용이하게하기 위해 일부 장면 전략은 WordTags 클래스에서 구현됩니다.
| 구현 방법 | 설명 | 주목 |
|---|---|---|
| 없음() | 빈 구현 | V0.10.0 지원 |
| 파일 (String FilePath) | 파일 경로를 지정합니다 | V0.10.0 지원 |
| 파일 (문자열 FilePath, 문자열 wordSplit, String tagsplit) | 파일 경로와 단어 분리기 및 태그 분리기를 지정하십시오. | V0.10.0 지원 |
| 지도 (Final Map <문자열, 세트> WordTagMap) | 지도에 따른 초기화 | V0.24.0 지원 |
| 라인 (수집 라인) | 문자열 목록 | V0.24.0 지원 |
| 라인 (수집 라인, 문자열 wordplit, String tagspli) | 문자열 목록, 단어 분리기 및 라벨 분리기 | V0.24.0 지원 |
| 체계() | 시스템 파일의 내장 구현, 네트워크 분류 통합 | V0.24.0 지원 |
| 기본값 () | 기본 정책은 현재 시스템입니다 | V0.24.0 지원 |
| 체인 (iwordtag ... 기타) | 체인 메소드는 여러 정책을 구현하기 위해 사용자 통합을 지원합니다 | V0.24.0 지원 |
민감한 단어 태그의 형식은 다음에敏感词tag1,tag2 에 기본적으로 기본적으로, 즉敏感词의 태그는 Tag1 및 Tag2임을 의미합니다.
예를 들어
五星红旗 政治,国家
모든 파일 라인 내용 및 지정된 문자열 내용에도 권장됩니다. 만족하지 않으면 사용자 정의 방식으로 구현하십시오.
V0.24.0부터 기본 단어 태그는 WordTags.system() 입니다.
참고 : 현재 데이터 통계는 인터넷에서 왔으며 많은 누락이 있습니다. 모두가 문제를 해결하고 계속 개선 할 수 있습니다 ...
SensitiveWordBs sensitiveWordBs = SensitiveWordBs . newInstance ()
. wordTag ( WordTags . system ())
. init ();
Set < String > tagSet = sensitiveWordBs . tags ( "博彩" );
Assert . assertEquals ( "[3]" , tagSet . toString ());여기서 압축 크기를 최적화하기 위해 해당 범주는 숫자로 표시됩니다.
숫자의 의미 목록은 다음과 같습니다.
0 政治
1 毒品
2 色情
3 赌博
4 违法
여기서 우리는 파일을 사용하는 방법을 보여주기 위해 파일을 예제로 가져옵니다.
final String path = "~ \ test \ resources \ dict_tag_test.txt" ;
// 演示默认方法
IWordTag wordTag = WordTags . file ( path );
SensitiveWordBs sensitiveWordBs = SensitiveWordBs . newInstance ()
. wordTag ( wordTag )
. init ();
Set < String > tagSet = sensitiveWordBs . tags ( "零售" );
Assert . assertEquals ( "[广告, 网络]" , tagSet . toString ());
// 演示指定分隔符
IWordTag wordTag2 = WordTags . file ( path , " " , "," );
SensitiveWordBs sensitiveWordBs2 = SensitiveWordBs . newInstance ()
. wordTag ( wordTag2 )
. init ();
Set < String > tagSet2 = sensitiveWordBs2 . tags ( "零售" );
Assert . assertEquals ( "[广告, 网络]" , tagSet2 . toString ()); 여기서 dict_tag_test.txt 우리의 사용자 정의 컨텐츠는 다음과 같습니다.
零售 广告,网络
민감한 단어를 얻을 때 해당 민감한 단어 태그 정보를 얻기 위해 해당 결과 처리 전략을 설정할 수 있습니다.
// 自定义测试标签类
IWordTag wordTag = WordTags . lines ( Arrays . asList ( "天安门 政治,国家,地址" ));
// 指定初始化
SensitiveWordBs sensitiveWordBs = SensitiveWordBs . newInstance ()
. wordTag ( wordTag )
. init ()
;
List < WordTagsDto > wordTagsDtoList1 = sensitiveWordBs . findAll ( "天安门" , WordResultHandlers . wordTags ());
Assert . assertEquals ( "[WordTagsDto{word='天安门', tags=[政治, 国家, 地址]}]" , wordTagsDtoList1 . toString ());天安门키워드의 태그를 사용자 정의 한 다음 FindAll의 결과 처리 전략이 WordResultHandlers.wordTags() 임을 지정하고 민감한 단어를 얻는 동안 해당 태그 목록을 얻을 수 있습니다.
때때로 우리는 콘솔 수정과 같은 민감한 단어의 로딩을 동적으로 설계하고 실시간으로 효력을 발휘할 수 있습니다.
v0.0.13 은이 기능을 지원합니다.
이 기능을 구현하고 이전 기능과 호환 되려면 두 인터페이스를 정의했습니다.
인터페이스는 다음과 같습니다. 자체 구현을 사용자 정의 할 수 있습니다.
반환 된 목록은 단어가 민감한 단어임을 의미합니다.
/**
* 拒绝出现的数据-返回的内容被当做是敏感词
* @author binbin.hou
* @since 0.0.13
*/
public interface IWordDeny {
/**
* 获取结果
* @return 结果
* @since 0.0.13
*/
List < String > deny ();
}예를 들어:
public class MyWordDeny implements IWordDeny {
@ Override
public List < String > deny () {
return Arrays . asList ( "我的自定义敏感词" );
}
}인터페이스는 다음과 같습니다. 자체 구현을 사용자 정의 할 수 있습니다.
반환 된 목록은 단어가 민감한 단어가 아님을 의미합니다.
/**
* 允许的内容-返回的内容不被当做敏感词
* @author binbin.hou
* @since 0.0.13
*/
public interface IWordAllow {
/**
* 获取结果
* @return 结果
* @since 0.0.13
*/
List < String > allow ();
}좋다:
public class MyWordAllow implements IWordAllow {
@ Override
public List < String > allow () {
return Arrays . asList ( "五星红旗" );
}
}물론 인터페이스가 사용자 정의 된 후에는 적용되도록 지정해야합니다.
보다 우아하게 사용하기 위해 부트 클래스 SensitiveWordBs 설계했습니다.
WordDeny (), wordallow ()를 통해 민감한 단어를 지정할 수 있으며, 민감하지 않은 단어를 지정하고 init ()를 통해 민감한 단어 사전을 초기화 할 수 있습니다.
SensitiveWordBs wordBs = SensitiveWordBs . newInstance ()
. wordDeny ( WordDenys . defaults ())
. wordAllow ( WordAllows . defaults ())
. init ();
final String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。" ;
Assert . assertTrue ( wordBs . contains ( text ));참고 : Init ()는 민감한 단어 DFA를 구축하는 데 시간이 걸립니다. 일반적으로 초기화를 적용 할 때 한 번만 초기화하는 것이 좋습니다. 초기화를 반복하는 대신!
다음과 같이 사용자 정의 구현을 테스트 할 수 있습니다.
String text = "这是一个测试,我的自定义敏感词。" ;
SensitiveWordBs wordBs = SensitiveWordBs . newInstance ()
. wordDeny ( new MyWordDeny ())
. wordAllow ( new MyWordAllow ())
. init ();
Assert . assertEquals ( "[我的自定义敏感词]" , wordBs . findAll ( text ). toString ());我的自定义敏感词민감한 단어 인 유일한 단어는 다음과 같습니다.测试민감한 단어가 아닙니다.
물론 여기에 우리의 모든 맞춤 구현이 있습니다. 일반적으로 시스템의 기본 구성 + 사용자 정의 구성을 사용하는 것이 좋습니다.
다음 방법을 사용할 수 있습니다.
WordDenys.chains() 메소드는 여러 구현을 동일한 iworddeny로 병합합니다.
WordAllows.chains() 메소드는 여러 구현을 동일한 iwordallow로 병합합니다.
예:
String text = "这是一个测试。我的自定义敏感词。" ;
IWordDeny wordDeny = WordDenys . chains ( WordDenys . defaults (), new MyWordDeny ());
IWordAllow wordAllow = WordAllows . chains ( WordAllows . defaults (), new MyWordAllow ());
SensitiveWordBs wordBs = SensitiveWordBs . newInstance ()
. wordDeny ( wordDeny )
. wordAllow ( wordAllow )
. init ();
Assert . assertEquals ( "[我的自定义敏感词]" , wordBs . findAll ( text ). toString ());그들 모두는 시스템 기본 구성 및 사용자 정의 구성을 동시에 사용합니다.
참고 : 새로운 WordBS를 초기화하므로 새 WordBS를 사용하여 판단하십시오. 이전 SensitiveWordHelper 도구 방법을 사용하는 대신 도구 메소드 구성이 기본값입니다!
예를 들어 실제로 사용하면 페이지 구성을 수정 한 다음 실시간으로 적용 할 수 있습니다.
데이터는 데이터베이스에 저장됩니다. 다음은 의사 코드의 예입니다. springsensitivewordconfig.java를 참조 할 수 있습니다
필수, 버전 v0.0.15 이상.
단순화 된 의사 코드는 다음과 같습니다. 데이터 소스는 데이터베이스입니다.
Myddwordallow 및 Myddworddeny는 데이터베이스를 소스로 기반으로하는 사용자 정의 구현 클래스입니다.
@ 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 ;
}
}민감한 어휘의 초기화는 시간이 많이 걸리므로 프로그램이 시작될 때 초기화를 시작하는 것이 좋습니다.
V0.6.0 이후 해당 벤치 마크 테스트를 추가하십시오.
BenchmarkTimestest
테스트 환경은 일반 노트입니다.
处理器 12th Gen Intel(R) Core(TM) i7-1260P 2.10 GHz
机带 RAM 16.0 GB (15.7 GB 可用)
系统类型 64 位操作系统, 基于 x64 的处理器
추신 : 다른 환경은 다르지만 비율은 기본적으로 안정적입니다.
테스트 데이터 : 100+ 문자열, 루프 10W 시간.
| 일련 번호 | 장면 | 시간이 많이 걸립니다 | 주목 |
|---|---|---|---|
| 1 | 형식 변환없이 민감한 단어 만 만드십시오 | 1470ms, 약 7.2W Qps | 극단적 인 성능을 추구하면 이와 같이 구성 할 수 있습니다 |
| 2 | 민감한 단어 만 만들고 모든 형식 변환을 지원합니다 | 2744ms, 약 3.7W Qps | 대부분의 시나리오를 충족하십시오 |
개별 중국어에서 민감한 단어를 제거하십시오. 중국에서는 문구가 잘못 판단되는 비율을 줄이기 위해 단일 단어로 간주되어야합니다.
개별 민감한 단어 변경을 지원합니까?
제거, 추가, 편집?
민감한 단어 태그 인터페이스 지원
민감한 단어를 처리 할 때 지원합니다
메모리 사용량 비교 + WordData의 최적화
사용자는 사용자 정의 문구를 지정하고 지정된 문구의 조합을 얻을 수 있도록하여보다 유연하게 만듭니다.
FormatCombine/CheckCombine/AllowDenyCombine 조합 정책, 사용자 사용자 정의를 허용합니다.
단어 점검 전략의 최적화, 통합 트래버스 + 변환
ThreadLocal 및 기타 성능 최적화를 추가하십시오
민감한 단어 Admin 민감한 단어 콘솔 v1.2.0 오픈 소스
민감한 단어 Aadmin v1.3.0 릴리스에서 분산 배포를 지원하는 방법은 무엇입니까?
오픈 소스 민감한 단어 도구의 01-Beginner
민감한 단어 도구를 구현하려면 02? 금지 된 단어를 구현한다는 아이디어를 명확히하십시오
03 지원 단어 중지 단어 중지 단어 최적화 및 특수 기호
04 민감한 단어 슬리밍 사전
05 민감한 단어의 DFA 알고리즘에 대한 설명 (트리 트리 알고리즘)
06에 민감한 단어 (더러운 단어) 의미없는 캐릭터를 무시하는 방법? 더 나은 필터링 효과를 달성합니다
더러운 단어 분류 태그에 대한 v0.10.0 예비 지원
v0.11.0- 민감한 단어의 새로운 특징 : 무의미한 문자 무시, 단어 태그 사전
v0.12.0에 민감한 단어/더러운 단어 라벨링 능력이 더욱 향상됩니다
v0.13.0에 민감한 단어 기능 버전 릴리스는 영어 단어로 전체 단어 일치를 지원합니다.
v0.16.1 민감한 단어의 새로운 기능의 사전 메모리 리소스 릴리스
v0.19.0- 반복 초기화없이 개별적으로 편집 한 민감한 단어의 새로운 기능을 갖춘 민감한 단어
v0.20.0 민감한 단어의 새로운 특성은 부분 일치가 아닌 모든 숫자와 일치합니다.
v0.21.0 민감한 단어의 새로운 기능을 갖춘 화이트리스트는 단일 편집을 지원하고, 화이트리스트가 블랙리스트를 포함 할 때 문제를 수정합니다.
Pinyin에서 Pinyin
Pinyin2hanzi Pinyin에서 한자
세그먼트 고성능 중국어 단어 세분화
Opencc4j 중국 전통 중국의 중국 전환을 단순화했습니다
NLP-Hanzi-similar 중국어 유사성
Word-Checker 철자 감지
민감한 단어 민감한 단어