【愚公系列】2023年03月 .NET CORE工具案例-ToolGood.Words敏感词过滤

举报
愚公搬代码 发表于 2023/03/31 23:06:35 2023/03/31
【摘要】 前言1.什么是敏感词过滤敏感词过滤是一种处理网络内容的技术,可以检测和过滤出网络中的敏感词汇。它通过给定的关键字或字符串,判断网络内容是否包含某些敏感信息,从而防止违反法律法规的信息流通。通常,可以使用两种方法来过滤敏感词:• 黑名单过滤:即定义一个黑名单,将所有敏感词择记录在其中,然后对输入的文本进行对比,如果发现有敏感词,就将其过滤掉。• 白名单过滤:即定义一个白名单,将所有不敏感的词汇...

前言

1.什么是敏感词过滤

敏感词过滤是一种处理网络内容的技术,可以检测和过滤出网络中的敏感词汇。它通过给定的关键字或字符串,判断网络内容是否包含某些敏感信息,从而防止违反法律法规的信息流通。

通常,可以使用两种方法来过滤敏感词:

• 黑名单过滤:即定义一个黑名单,将所有敏感词择记录在其中,然后对输入的文本进行对比,如果发现有敏感词,就将其过滤掉。

• 白名单过滤:即定义一个白名单,将所有不敏感的词汇记录在其中,然后对输入的文本进行对比,如果发现有不在白名单中的词汇,就将其过滤掉。

2.ToolGood.Words是什么

ToolGood.Words是一款高性能非法词(敏感词)检测组件,附带繁体简体互换,支持全角半角互换,获取拼音首字母,获取拼音字母,拼音模糊搜索等功能。

C#语言,使用StringSearchEx2.Replace过滤,在48k敏感词库上的过滤速度超过3亿字符每秒。(cpu i7 8750h)

3.ToolGood.Words的相关概念

ToolGood.Words的敏感词检测类主要有:StringSearch、StringSearchEx、StringSearchEx2、WordsSearch、WordsSearchEx、WordsSearchEx2、IllegalWordsSearch介绍如下:

• StringSearch、StringSearchEx、StringSearchEx2、StringSearchEx3:搜索FindFirst方法返回结果为string类型。

• WordsSearch、WordsSearchEx、WordsSearchEx2、WordsSearchEx3:搜索FindFirst方法返回结果为WordsSearchResult类型, WordsSearchResult不仅仅有关键字,还有关键字的开始位置、结束位置,关键字序号等。

• IllegalWordsSearch:过滤非法词(敏感词)专用类,可设置跳字长度,默认全角转半角,忽略大小写,跳词,重复词,黑名单,搜索FindFirst方法返回为IllegalWordsSearchResult,有关键字,对应原文,开始、位置,黑名单类型。

• IllegalWordsSearch、StringSearchEx、StringSearchEx2、WordsSearchEx、WordsSearchEx2 使用Save、Load方法,可以加快初始化。

• 共同方法有:SetKeywords、ContainsAny、FindFirst、FindAll、Replace

• IllegalWordsSearch独有方法:SetSkipWords(设置跳词)、SetBlacklist(设置黑名单)。

• IllegalWordsSearch字段UseIgnoreCase:设置是忽略否大小写,必须在SetKeywords方法之前,注:使用Load方法则该字段无效。

• StringSearchEx3、WordsSearchEx3为指针版优化版,实测时发现性能浮动比较大。

ToolGood.Words的源码网站:https://github.com/toolgood/ToolGood.Words


一、ToolGood.Words敏感词过滤

1.安装包

ToolGood.Words



2.定义模型类

//用于核查敏感词
public class MinganCheckInput
{
[MinGanCheck]
public string Text { get; set; }
}

//用于替换敏感词
public class MinganReplaceInput
{
[MinGanReplace]
public string Text { get; set; }
}


3.定义敏感词实现类

1、接口

public interface IMinGanCheckValidator
{
ValidationResult IsValid(object value, ValidationContext validationContext);
}

public interface IMinGanReplaceValidator
{
void Replace(object value, ValidationContext validationContext);
}


2、实现类

public class MinGanCheckValidator : IMinGanCheckValidator
{
public ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value is string v)
{
if (!String.IsNullOrEmpty(v))
{
if (MinGanProvider.Instance.IllegalWordsSearch.ContainsAny(v))
{
return new ValidationResult("存在敏感词", new[] { validationContext.MemberName });
}
// 检查拼音
if (MinGanProvider.Instance.IllegalWordsSearch.ContainsAny(WordsHelper.GetPinyin(v)))
{
return new ValidationResult("存在敏感词",new []{ validationContext.MemberName });
}
// todo:其他变种
}
}
return ValidationResult.Success;
}
}

public class MinGanReplaceValidator : IMinGanReplaceValidator
{
public void Replace(object value, ValidationContext validationContext)
{
if (value is string v)
{
if (!String.IsNullOrEmpty(v))
{
v = MinGanProvider.Instance.IllegalWordsSearch.Replace(v);
SetPropertyByName(validationContext.ObjectInstance,validationContext.MemberName, v);
}
}
}

static bool SetPropertyByName(Object obj, string name, Object value)
{
var type = obj.GetType();
var prop = type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
if (null == prop || !prop.CanWrite) return false;
prop.SetValue(obj, value, null);
return true;
}
}


4.定义特性

/// <summary>
/// 敏感词检查的特性,一匹配就抛异常
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class MinGanCheck : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
return validationContext.GetService<IMinGanCheckValidator>().IsValid(value, validationContext);
}
}

/// <summary>
/// 敏感词替换
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class MinGanReplace : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
validationContext.GetService<IMinGanReplaceValidator>().Replace(value, validationContext);
return ValidationResult.Success;
}
}


5.添加配置文件

{
"IllegalKeywords": [
"xxxxxxx",
]
}

{
"IllegalUrls": [
"xxxxxxx",
]
}

#region 添加配置文件
builder.Configuration.AddJsonFile("IllegalKeywords.json", optional: false, reloadOnChange: true);// 配置可热重载
builder.Configuration.AddJsonFile("IllegalUrls.json", optional: false, reloadOnChange: true);// 配置可热重载
#endregion


6.配置热更新

public sealed class MinGanProvider
{
private static readonly Lazy<MinGanProvider>
lazy =
new Lazy<MinGanProvider>
(() => new MinGanProvider());

public static MinGanProvider Instance { get { return lazy.Value; } }

private MinGanProvider()
{
IllegalWordsSearch = new IllegalWordsSearch();
}

public readonly IllegalWordsSearch IllegalWordsSearch;


public void SetKeys(List<string> keys)
{
if (keys!=null&&keys.Any())
{
var allKeys = new List<string>();
foreach (var k in keys)
{
allKeys.Add(k); // 增加词汇
allKeys.Add(WordsHelper.ToTraditionalChinese(k)); // 增加繁体
allKeys.Add(WordsHelper.GetPinyin(k)); // 增加拼音
}
IllegalWordsSearch.SetKeywords(allKeys);
}

}
}


#region 配置热更新
MinGanProvider.Instance.SetKeys(builder.Configuration.GetSection("IllegalKeywords").Get<List<string>>());
ChangeToken.OnChange(() => app.Configuration.GetReloadToken(), () =>
{
// 敏感词重载
MinGanProvider.Instance.SetKeys(builder.Configuration.GetSection("IllegalKeywords").Get<List<string>>());
});
#endregion


7.运行

[ApiController]
[Route("[controller]/[action]")]
public class MinganController : ControllerBase
{
[HttpGet]
public string Check([FromQuery]MinganCheckInput input)
{
return input.Text;
}

[HttpGet]
public string Replace([FromQuery]MinganReplaceInput input)
{
return $"替换后的字段为:{input.Text}";
}
}


测试


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。