Java中的亵渎过滤器性能


9

我需要在基于Java的Web应用程序中过滤掉用户提交内容中的亵渎行为。客户知道斯肯索普问题克洛提克问题,并已接受后果。拜托,我不想就缺乏审查制度的优点进行辩论。

有两个数据位:

  1. 用户提交的内容,可能包含500个字左右;
  2. 单列数据库表,其中包含不允许的单词。该表中可能有成千上万的记录。

目前的解决方案对我来说似乎是错误的:

  1. 整个表在启动时装入到Singleton中的静态String []中(因此驻留在内存中)。
  2. 对于每个用户提交,我们遍历数组并执行.indexOf()以查看String []中是否有任何给定单词出现在提交中。
  3. 如果出现,我们将替换为%$#@%样式的字符。这是通过以下方式完成的:标记用户提交的内容,再次将整个用户提交作为标记循环,并替换找到的单词的每个实例。

此解决方案可能会有出色之处,但我对此表示怀疑。看了一会儿,我找不到路。

问题是,有什么解决方案能够提供良好的性能,并希望在我因未能过滤掉一些我从未听说过的晦涩词汇而被解雇后,对未来的开发人员保持理智的态度?


您说这对您来说似乎是错的,而没有告诉我们您为什么认为错了。然后,您在不告知我们的情况下,要求提供一种性能出色的解决方案,而当前的解决方案还不够。您每秒收到多少文本,可以处理多少文本?
用户未知,

我认为解决方案是错误的,主要是因为我正在使用的代码库不足且草率。鉴于我的偏见,我不相信自己的不信任。我认为别人的意见将是有益的。引起我注意的事情是String [](这是1999年?),它遍历非常大的String []而不是用户提交的数据集少得多,并在String []循环内嵌套了一个循环与令牌化的用户提交,等等。预期的利用率未指定,理想情况下,具有合理性能的优雅解决方案将是不错的选择。
blueishgoldfish 2011年

2
“合理的表现”可能意味着任何事情。如果您没有具体目标,就无法确定自己是否达到目标。如果您加快了流程,使其速度提高了100倍,这是目标吗?用户正在等待1ms还是1 / 10s?用户将不会从您的工作中受益。
用户未知,

Answers:


18

智能地进行单词过滤的唯一方法是使用语音匹配系统。几年前,我用Java为一个非常流行的大型多人在线游戏编写了一个非常有效的亵渎过滤器,该游戏适用于青少年。

它基于经过高度修改的Double MetaPhone算法,该算法经过调整后更加精确,而不是默认值,即默认值是要匹配尽可能多的内容。它是如此有效,因为它能收集与实际单词相同的拼写错误和语音拼写。我说l33t说话和txt发言的音位算法为好,使之更一三/四音位算法。

它具有一个预处理器,可以压缩运行中的字母并检测孩子等事物,w o r d s通过智能地将这些字母压缩在一起并消除运行中的重复项(例如wwoorrddss)来放置事物,它专门用于英语。

8年前,它的速度足够快,可以用于实时聊天系统流中,而在单个核心CPU系统上没有成千上万用户的明显延迟。

我们在数据库的表中有一个用Metaphone编码的单词列表,它被加载到一个静态Map中,该映射非常小,而且我们无需执行任何特殊操作即可访问被禁止的单词列表,我能够添加使用相同技术的短语检测几乎免费。

当然,我有一个运行日志,记录了成千上万试图实时中断系统的孩子的所有聊天记录,因此我可以使用非常全面的数据集。我进行记录的方式是,当某人以肯定的方式触发了过滤器时,我记录了接下来的一些聊天消息,这些消息没有从他们那里触发过滤器,这样,如果他们确实找到了围绕特定单词或短语的方法,我可以适应我的系统并抓住这一点。短短几周后,我获得了相当不错的证明。


3
此解决方案似乎是最好的。问题是(或者在这一点上)我不得不在一个下午解决它。如果有足够的时间,我要么采用Double MetaPhone方法,要么雇用您这样做。:-)
blueishgoldfish 2011年

所以,我想现在有一半人会停止玩游戏:D
DavorŽdralo2011年


0

不用加载到静态String []中,而是利用HashMap []或其他类型的二叉树(如果您想改善搜索),使字符串成为哈希中的键。用空格分隔字符串并删除标点符号。然后,您可以查询HashMap中字符串拆分中的每个单词;如果哈希表返回非null值,则表示您输入的单词不好。

失败的是克洛布蒂奇(Clbuttic)问题,其中有人在坏单词ex周围添加随机字符。 bhassda


我认为最后的警告是使该解决方案几乎无用的原因-除全字匹配之外,没有办法将其扩展到其他任何内容。

这是一个公平的声明;但是要想逃避亵渎性过滤器,就很难捕获人脑中想出的所有可能事物。您总是可以使用OR语句创建一个庞大的正则表达式,以组合所有选项,然后将正则表达式与输入进行匹配。或者,您可以从数据库中使用带有输入的RLIKE的“坏词字段”从数据库中进行选择。Return表示错误的单词,也将返回错误的单词。

@Suroot并不难捕获几乎所有带有语音匹配的单词或短语,就像我的问题所谈论的那样。绝对匹配永远不会起作用或无法扩展,但是一旦您进行调谐,语音匹配的工作时间将接近100%。

-1

无论如何,使用语音系统并不是唯一的解决方案,但是它可能是最简单的,因为有很多开源库都在做这种事情。

最困难的部分总是成为任何算法的匹配部分,听起来您的匹配非常缓慢且幼稚。您不能假设没有某种形式的辅助检查,indexOf将正确匹配。

此外,您最终将遍历整个String N次,其中N是黑名单上的单词数。使用Set或HashMap的建议肯定会有所改善。

在大多数情况下,基于线性状态的算法是最好和最快的。我为Clean Speak编写了解决方案,该解决方案将这种算法与预处理语音匹配系统一起使用。这是嵌入亵渎性语言时唯一不会变得复杂的解决方案(如果foo是亵渎性语言,则嵌入是foosucker)并能够保持较高的性能。如果不实现新的法典,它也可以很好地扩展到其他语言。

最后,通常需要避免任何形式的预处理。在大多数情况下,当您处理字符串中的每个字符时,可以以线性方式执行相同的操作。

当然,我建议从长远角度考虑其他解决方案,因为在大多数处理用户生成内容的应用程序中,不仅仅是亵渎性过滤更为复杂。通常,您还希望过滤个人信息,例如电子邮件和社会保险号,有时还过滤URL之类的东西。另外,我们发现大多数应用程序都需要某种形式的审核系统和内容搜索。这些大大增加了复杂性。


-2

在这种情况下,您要做的是确定两个单词列表中哪个较小。假设您的“ verboten”列表包含2000个单词,最大用户提交量为500个单词。在这种情况下,您将遍历用户提交内容中的单词列表,并在禁用单词列表中逐一查找它们,反之亦然。

我要进行的另一项更改是,您不会在String []中保留禁用单词的列表-如果在数组中搜索,则用户提交中的每个单词都会有O(n)个搜索。真不好 我会尝试将您要查找的数据结构放入某种具有更好查询性能的关联容器或树结构中(用log n代替n)。这里的挑战是,如果将用户提交的内容放入此容器中,则必须跟踪单词的位置,以便在遇到搜索结果时可以重新构造输入或更新输入字符串。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.