• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
愚公搬代码
帮助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}";
    }
}

学新通
测试
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhghekbc
系列文章
更多 icon
同类精品
更多 icon
继续加载