强大灵活的脏字过虑:1万字文章过虑1万关键词用时只要1毫秒

优采云 发布时间: 2020-08-09 14:27

  这几天刚整理完Kudy.Net项目中关键词过虑的功能。关键词过虑在网站开发中也算是比较常见的需求了,特别是在SNS社区网站。在网上找的相关文章都达不到我的要求,所以就自己按照过虑的特征专门写了个KeywordFilter,可能满足基本的过虑要求,性能也不错。它有如下特征:

  一、允许你自定义匹配到关键词时返回的结果,例如匹配到“日你”,你可以在原文中显示诸如:“”、“**”、“[已过虑]”...

  二、允许你按关键词或则关键词的使用频度的排序的优先次序进行过虑。

  三、允许大小写是否敏感(性能上几乎不变),可设置关键词中可跳过的字符,例如设置可跳字符为“▇☆”,关键词里有“*敏*感*词*”,那么“我▇爱☆☆你”也会被成功过虑。

  备注:如果设置了可跳字符,只会过虑有关键词出现的地方,例如前面“▇我▇爱☆☆你▇”过虑后只有“▇▇”。(哈哈,发现博客园的过虑并没有这功能)

  既然是简单的处理过虑,里面其实没有做动词的处理,所以有些语句可能会被误报,只要设置重要的敏感禁用词即可。

  实现思路:关键字过虑实现的思路及Aho–Corasick高效字符串匹配算法应用(附算法C#实现和测试)

  另在一文中见到的过虑效率也不错,请到这儿看,测试了它的速率是本人的约1.5倍,但是它并没有不分辨大小写、可跳字符、关键词排序和多元化自定义关键词替换的功能,我更关心的是功能上的实用和灵活性。

  更多请关注:KudyStudio文章目录

  功能实现的相关成员有:Keyword、KeywordOrder、KeywordFormatter、KeywordFilterResult、KeywordFilter、HighlightFormatter、Highlighter。

  1.Keyword类,主要有两个属性,Text和Frequency,分别表示关键词文本与它的使用频度(这个属性是可选的),如果从文本中转换为关键词列表,那文本格式是这样的:

  Keyword1

  Keyword2

  或

  Keyword1|Frequency1

  Keyword2|Frequency2

   [Serializable]

public sealed class Keyword

{

public Keyword(string text);

public Keyword(string text, int frequency);

public static implicit operator string(Keyword keyword);

public static implicit operator Keyword(string keyword);

public string Text { get; }

public int Frequency { get; set; }

public override bool Equals(object obj);

public override int GetHashCode();

public override string ToString();

}

  2.KeywordOrder枚举,表示过虑时匹配的次序,允许你按文本或使用频度排序,定义如下:

   [Serializable]

public enum KeywordOrder

{

None = 0,

Ascending = 1,

Descending = 2,

ByFrequencyAscending = 3,

ByFrequencyDescending = 4,

}

  3.KeywordFormatter类,这个是抽象类,它的作用就是在匹配到关键词时如何低格关键词并返回,里面默认实现了常量和重复字符的Formatter,如果还须要特殊的低格需求,只要承继KeywordFormatter并实现Format(string keyword)方法即可,下面讲到的HighlightFormatter就是其中一个事例。

   public abstract class KeywordFormatter

{

public static readonly KeywordFormatter ToEmpty;

public static readonly KeywordFormatter ToIterantStar;

public static KeywordFormatter CreateConstFormatter(char replacement);

public static KeywordFormatter CreateConstFormatter(string replacement);

public static KeywordFormatter CreateIterantCharFormatter(char replacement);

public abstract string Format(string keyword);

}

  4.KeywordFilterResult类,它表示过虑结果,包括过虑后的字符串和被过虑的关键词列表,定义如下:

   public sealed class KeywordFilterResult

{

public KeywordFilterResult(string result, IEnumerable keywords);

public string Result { get; }

public List Keywords { get; }

}

  5.KeywordFilter类,这个类是重点,它是实现过虑的核心,其它类只是功能需求上的辅助成员。要注意的是,它的初始化是须要一定的开支的(关键词量大的时侯),所以对于大量的关键词,建议不要使用它的静态方式来进行过虑,而是先初始化实例,再重复的调用实例的方式来过虑。里面还有个方式ContainsAny使你快速判定上面是否包括有关键词。

   public sealed class KeywordFilter

{

public KeywordFilter(IEnumerable keywords);

public KeywordFilter(IEnumerable keywords);

public KeywordFilter(IEnumerable keywords, IEnumerable skipChars);

public KeywordFilter(IEnumerable keywords, IEnumerable skipChars);

public ReadOnlyCollection Keywords { get; }

public ReadOnlyCollection SkipChars { get; }

public bool ContainsAny(string original);

public bool ContainsAny(string original, bool ignoreCase);

public bool ContainsAny(string original, KeywordOrder order);

public bool ContainsAny(string original, KeywordOrder order, bool ignoreCase);

public KeywordFilterResult Filter(string original);

public KeywordFilterResult Filter(string original, KeywordFormatter formatter);

public KeywordFilterResult Filter(string original, KeywordFormatter formatter, bool ignoreCase);

public KeywordFilterResult Filter(string original, KeywordFormatter formatter, KeywordOrder order);

public KeywordFilterResult Filter(string original, KeywordFormatter formatter, KeywordOrder order, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords);

public static KeywordFilterResult Filter(string original, IEnumerable keywords);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, KeywordOrder order);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, KeywordOrder order);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, KeywordOrder order, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, KeywordFormatter formatter, KeywordOrder order, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, IEnumerable skipChars, KeywordFormatter formatter, KeywordOrder order, bool ignoreCase);

public static KeywordFilterResult Filter(string original, IEnumerable keywords, IEnumerable skipChars, KeywordFormatter formatter, KeywordOrder order, bool ignoreCase);

public static List LoadKeywords(string filePath);

public static List LoadKeywords(string filePath, Encoding encoding);

public static List ParseKeywords(string keywordsText);

public static void SaveKeywords(IEnumerable keywords, string filePath);

public static void SaveKeywords(IEnumerable keywords, string filePath);

public static void SaveKeywords(IEnumerable keywords, string filePath, Encoding encoding);

public static void SaveKeywords(IEnumerable keywords, string filePath, Encoding encoding);

}

  到此,过虑功能成员介绍完了,下面还有两个成员是在KeywordFilter基础上实现的高亮功能HighlightFormatter和Highlighter。

   public sealed class HighlightFormatter : KeywordFormatter

{

public static readonly HighlightFormatter Html;

public HighlightFormatter(string prefix, string postfix);

public string Postfix { get; }

public string Prefix { get; }

public static KeywordFormatter Create(string prefix, string postfix);

public override string Format(string keyword);

}

   public static class Highlighter

{

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, bool ignoreCase);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, KeywordOrder order);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, bool ignoreCase);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, KeywordOrder order);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, KeywordOrder order, bool ignoreCase);

public static string Highlight(string original, IEnumerable keywords, HighlightFormatter formatter, KeywordOrder order, bool ignoreCase);

}

  OK,下面开始测试了。

  关键词为:"SB|法_轮_功(博客园过虑了)|日你|日你奶奶"

  可跳字符:"▇☆"

  原文本:....有博客园要过虑的词,不贴下来了,请看下边的测试结果,最后一组过虑弄成了【关键词】,是因为用了自定义的Formatter。

  

  

  上面只是功能上的测试,下面是1000词/1000字文章/300可跳字符和10000词/10000字文章/300可跳字符性能上的测试结果,可以看见,小量关键词里,KeywordFilter实例化时间极少,但是达到1万关键词时用了252ms,而过虑所用时间只是从后面的0ms变为1ms,关键词达10万时也只用了11ms(本人笔记本的配置情况),可见过虑的高效。大家有兴趣的话请下载测试源码来自己看。

  

  

  是否过虑成功?那是必须的,一词不漏:

  

  高亮在KeywordFilter的基础上就简单实现了,只是实现了个HighlightFormatter,怎么高亮主要看前缀和后缀,下面是测试html高亮的结果:

  

  至此,文章结束,大家帮忙点一下推荐哦,提供测试源码下载:KudyStudioFilteringTest.rar

  更多请关注:KudyStudio文章目录

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线