您如何实现良好的亵渎过滤器?


207

我们中的许多人需要处理用户输入,搜索查询以及输入文本可能包含亵渎或不受欢迎语言的情况。通常,这需要过滤掉。

在哪里可以找到各种语言和方言的咒骂单词的好清单?

是否有API可供包含良好列表的来源使用?还是仅使用某些参数简单地说“是的干净”或“没有这个脏”的API?

有什么好的方法可以捕获试图欺骗系统的人员,例如a $$,azz或a55?

如果您提供PHP解决方案,则可以加分。:)

编辑:回答说只是避免程序性问题的答案:

我认为,例如当用户可以使用公共图像搜索来查找添加到敏感社区池中的图片时,就可以使用这种过滤器。如果他们可以搜索“阴茎”,那么他们可能会得到很多照片。如果我们不想要这样的图片,那么将单词作为搜索词是一个很好的看门人,尽管公认这不是万无一失的方法。首先获取单词列表是真正的问题。

因此,我实际上指的是一种找出单个令牌是否脏的方法,然后直接禁止它。我不会像完全热闹的“长颈长颈鹿”参考文献那样阻止这种情绪。您无能为力。:)


12
可惜的是,所有最重要的答案都是对编程挑战的生存主义和失败主义的转移。随着诸如Mechanical Turk之类的“电子人”计算服务日渐盛行,几乎所有软件都变得社交化,具有启发性的标记内容并将其引起主持人的注意比以往任何时候都更加重要!
JasonSmith,2009年

10
请注意语言环境,尤其是在使用i18n时。我曾经尝试为我要开设的课程设置一个Google小组,名为“ Sanal ortamdagörselleştirme”,这对于“虚拟媒体的可视化”来说是土耳其语。Google愚蠢到足以拒绝它,因为标题中包含“ anal”一词。Sanal [tr] = Virtual [en],Google无耻地指责我亵渎我!:D请不要让这种奇怪的事情发生。
edgerunner's

如果您搜索西班牙语单词该怎么办?实际上,您可以通过这种方式绕过Google图片过滤器(如果您已本地化为其他语言)。
new123456

另一个建议是不要禁止使用这些单词,而要注册使用它们的用户。如果用户/ IP的数量超过2、3或您想要的任何数量,请阻止该人。两者都不是万无一失的,但是与写“蓬松的白色兔子”而不是“猫”相比,被阻止并且必须更改用户/ IP /两者都更加不便。一部分,用户不知道他们不能使用哪些单词或表达式,因此他们不能像被禁止那样轻易地猜测不同的坏词。
Francisco Presencia,2012年

1
亵渎过滤器是个坏主意。很难区分试图欺骗系统的人(“骗你!”)和合法谈论完全适当的东西(“我喜欢巧克力软糖”)
clickbait

Answers:


176

淫秽过滤器:坏主意,还是令人难以置信的鼓励坏主意?

同样,人们也不会忘记《 Toontown's SpeedChat的不朽历史》,即使使用“安全字白名单”,也导致14岁的孩子迅速绕开它: “我想把长颈长颈鹿粘在蓬松的白色兔子身上”。

底线:最终,对于您实现的任何系统,绝对没有替代人为检查的(无论是同行还是其他方式)。可以随意实施一个基本工具来摆脱偷渡行为,但是对于确定的巨魔,您绝对必须使用基于非算法的方法。

一个消除匿名性并引入问责制的系统(Stack Overflow做得很好)也很有用,特别是为了帮助对抗John Gabriel的GIFT

您还问到可以从哪里获得亵渎列表-从一个开源项目中检出Dansguardian-从源代码中获取默认亵渎列表。您还可以下载其他第三方短语列表作为代理,这可能对您有所帮助。

编辑问题以进行编辑:感谢您对要执行的操作的说明。在这种情况下,如果您只是尝试做一个简单的单词过滤器,则有两种方法可以实现。一种是使用您要检查的所有禁止短语创建一个长的正则表达式,而只用它进行正则表达式查找/替换。正则表达式如:

$filterRegex = "(boogers|snot|poop|shucks|argh)"

然后使用preg_match()在您的输入字符串上运行它,以全面测试匹配项,

preg_replace()将其清空。

您还可以使用数组而不是单个长的正则表达式来加载这些功能,对于长单词列表,它可能更易于管理。有关如何灵活使用数组的一些良好示例,请参见preg_replace()

有关其他PHP编程示例,请参见此页面,其中提供了一些高级的用于单词过滤的通用类该类 *位于被删节单词的中心字母之外,并且该先前的Stack Overflow问题也有一个PHP示例(其中最重要的部分是基于SQL的过滤词方法-如果您发现不必要的话,可以省去leet-speak补偿器)。

您还添加了:“首先获取单词列表是真正的问题。 ”-除了一些以前的Dansgaurdian链接之外,您可能会发现这个方便的458个单词的.zip很有帮助。


@JPLemme:是的,我应该在之后加上[sic],因为这是Atwood拼写的方式。:)
HanClinto

“企鹅俱乐部”,增加了数百个条目他们亵渎过滤器每天raphkoster.com/2008/05/09/...
弗兰克农民

6
在你的正则表达式选项的单词边界包装将阻止clbuttic错误
中日韩

@ck:仅当您不担心能够过滤出拼写错误的单词“ F * ckkkk yo's assss”时:)我不确定我是否相信自己的巨魔具有非常精确的拼写。
HanClinto

1
如果你想听到来自众所周知的马嘴的“蓬松的白色兔子”的故事,这是一个播客节目现在:socialmediaclarity.tumblr.com/post/70499341079/...
F.兰德尔农民

44

虽然我知道这个问题相当古老,但这是一个普遍存在的问题...

亵渎过滤器是有原因的,也有其独特的需求(请参阅Wikipedia条目),但是由于非常不同的原因,它们常常达不到100%的准确度;上下文准确性

它(完全)取决于您要实现的目标-最基本的是,您可能想覆盖“ 七个脏话 ”,然后再覆盖一些...一些企业需要过滤最基本的亵渎内容:基本发誓说单词,URL或什至是个人信息等等,但其他人则需要防止非法帐户命名(例如Xbox live)或更多。

用户生成的内容不仅包含潜在的脏话,还可能包含对以下内容的令人反感的引用:

  • 性行为
  • 性倾向
  • 宗教
  • 种族
  • 等等...

并有可能以多种语言显示。到目前为止,Shutterstock已经开发了10种语言的基本脏话列表,但是它仍然是基本的,并且非常针对他们的“标记”需求。网络上还有许多其他列表。

我同意这个公认的答案,即这不是一门明确的科学,并且语言是一个不断发展的挑战,而是90%的捕获率优于0%的挑战。这完全取决于您的目标-您要达到的目标,获得的支持水平以及消除不同类型的亵渎行为的重要性。

在构建过滤器时,您需要考虑以下元素以及它们与项目的关系:

  • 字词/词组
  • 首字母缩略词(FOAD / LMFAO等)
  • 误报(单词,地点和名称,例如“ mishit”,“ scunthorpe”和“ titsworth”)
  • URL(色情网站是很明显的目标)
  • 个人信息(电子邮件,地址,电话等-如果适用)
  • 语言选择(默认情况下通常为英语)
  • 审核(如果有的话,如何与用户生成的内容进行交互以及如何处理)

您可以轻松构建一个亵渎过滤器,以捕获90%以上的亵渎行为,但您永远不会达到100%。只是不可能。您想要越接近100%,就越难...过去构建了一个复杂的亵渎引擎,每天处理超过500K实时消息,我将提供以下建议:

一个基本的过滤器将涉及:

  • 建立适用的亵渎清单
  • 开发一种处理亵渎行为的方法

中等复杂的文件管理器将涉及(除了基本过滤器之外):

  • 使用复杂的模式匹配来处理扩展派生(使用高级正则表达式)
  • Leetspeak(l33t)打交道
  • 处理误报

复杂的过滤器将涉及以下几个方面(除了中等过滤器之外):

  • 白名单和黑名单
  • 短语/术语的朴素贝叶斯推理过滤
  • Soundex功能(其中一个词听起来像另一个词)
  • 莱文施泰因距离
  • 抽干
  • 人工主持人可帮助引导过滤引擎通过示例进行学习,或者在没有指导的情况下匹配不够准确(自我/持续改进系统)
  • 也许某种形式的AI引擎

28

我不知道有什么好的库,但是无论您做什么,请确保您在使内容通过的方向上犯了错误。我所处理的系统不允许我使用“ mpassell”作为用户名,因为它包含“ ass”作为子字符串。这是疏远用户的好方法!


17
或在飞行的太空飞船游戏中禁止使用“座舱”
Shinhan

24

在我的工作面试中,正在面试我的公司CTO试用了我用Java编写的文字/网络游戏。在整个牛津英语词典的单词表中,第一个被猜到的单词是什么?

当然,英语中最脏的词。

不知何故,我仍然得到了工作机会,但随后我找到了亵渎单词列表(与这一样)),并编写了一个快速脚本以生成没有所有不良单词的新词典(甚至不必查看列表) 。

对于您的特殊情况,我认为将搜索结果与真实单词进行比较听起来像是使用单词列表的方式。其他样式/标点需要更多的工作,但我怀疑用户是否会经常使用它而成为问题。


8
没话题,但是最粗话是什么?我一直认为它是c字或n字,但我假设人们认为f字是
Jeff

2
“我怀疑用户是否会经常使用它而成为问题”,希望还活着。一旦用户迷失了过滤器,他们将努力寻找规避的方法。可以简单地将字母替换为数字,以奇数放置空格等)。
BryanH '11

21

一个亵渎的过滤系统将永远不会是完美的,即使程序员很自信并且能跟上所有裸露的发展

就是说,任何“顽皮的单词”列表的表现都可能与其他任何列表一样好,因为根本的问题是对语言的理解,这在当前技术中几乎是很难解决的

因此,唯一可行的解​​决方案是双重的:

  1. 准备经常更新字典
  2. 雇用人工编辑来纠正误报(例如“ clbuttic”而不是“ classic”)和误报(糟糕!错过了!)

1
只需在单词的两边都留有空格,然后在句号后面停下来,不是吗?
David D

1
没有人,只适用于最琐碎的案件。我们在这里与人类打交道,他们非常聪明:)
Steven A. Lowe

14

防止令人反感的用户输入的唯一方法是阻止所有用户输入。

如果您坚持允许用户输入并需要进行审核,那么请加入人工版主。



7

关于“欺骗系统”子问题,您可以在搜索之前通过同时标准化“坏词”列表和用户输入的文本来处理该问题。例如,使用一系列正则表达式(如果PHP拥有,则使用tr)将[z $ 5]转换为“ s”,[4 @]为“ a”,等等,然后将标准化的“坏词”列表与标准化的进行比较文本。请注意,尽管我目前无法想到任何实际情况,但标准化可能会导致其他误报。

更大的挑战是想出一种让人们引用“ 比剑强大”同时阻止“ peni s”的东西。


14
不要忘了expert-exchange.com和pen-island.com。这些网站网址曾经不包含连字符。
BryanH

7

提防本地化问题:一种语言中的脏话可能是另一种语言中的正常词。

一个当前的例子:ebay使用字典方法从反馈中过滤掉“坏词”。如果您尝试输入德语翻译“这是一次完美的交易”(“ das war eine perfekte Transaktion”),则ebay会因为不当用语而拒绝反馈。

为什么?因为德语单词“ was”是“ war”,而“ war”在ebay词典中是“ bad words”。

因此,请注意本地化问题。


6

如果您可以执行Digg / Stackoverflow之类的操作,让用户可以对淫秽内容进行下注/标记,请这样做。

然后,您需要做的就是查看“顽皮的”用户,并在他们违反规则时阻止他们。


4

我参加聚会有点晚了,但是我有一个解决方案,对于某些阅读本文的人可能有用。它在javascript中而不是在php中,但是有一个合理的理由。

完全公开,我写了这个插件...

无论如何。

我采用的方法是允许用户“选择加入”他们的亵渎过滤。默认情况下,基本上会亵渎语言,但如果我的用户不想阅读它,则不必这样做。这也有助于解决“ l33t sp3 @ k”问题。

这个概念很简单 如果客户帐户启用亵渎性过滤,则由服务器注入的插件。从那里开始,只有两条简单的线遮盖了咒骂。

这是演示页面
https://chaseflorell.github.io/jQuery.ProfanityFilter/demo/

<div id="foo">
    ass will fail but password will not
</div>

<script>
    // code:
    $('#foo').profanityFilter({
        customSwears: ['ass']
    });
</script>

结果

***将失败,但密码不会


这是一个 jsFiddle的工作演示,可以伴随这个答案。
Chase Florell

很天真。未过滤a$$
Winger Sendon '16

3
@EmperorAiman从来没有打算过滤掉l33t说话。我不建议尝试对此进行过滤,因为这是一场失败的战斗。我发布的亵渎过滤器是“内置的,目的是允许用户“选择加入”亵渎过滤器”。表示最好在默认情况下允许亵渎的网站上使用。如果要过滤a$$,则将其添加到过滤器列表中。
Chase Florell '16

4

我收集了12种语言的2200个坏词:en,ar,cs,da,de,eo,es,fa,fi,fr,hi,hu,it,ja,ko,nl,no,pl,pt,ru,sv ,th,tlh,tr,zh。

提供MySQL转储,JSON,XML或CSV选项。

https://github.com/turalus/openDB

我建议您将这个SQL执行到数据库中,并在用户每次输入内容时进行检查。


2

别。这只会导致问题。我对亵渎过滤器的一个私人经历是,我被IRC频道踢/禁赛的时间,因为我提到自己“要经过通往汉考克的桥几个小时”或类似的事情。


2

我同意HanClinto在此讨论中更高的职位。我通常使用正则表达式对输入文本进行字符串匹配。这是徒劳的,因为就像您最初提到的那样,您必须在“阻止”列表中明确说明网络上流行的每种技巧。

顺便说一句,尽管其他人正在讨论审查制度的伦理,但我必须同意某种形式的网络是必要的。有些人只是喜欢发布低俗的内容,因为它可以立即冒犯大批人,而且绝对不需要作者考虑。

谢谢你的想法。

HanClinto统治!


2

一旦有了要过滤的一些不良单词的良好MYSQL表(我从此线程中的链接之一开始),您可以执行以下操作:

$errors = array();  //Initialize error array (I use this with all my PHP form validations)

$SCREENNAME = mysql_real_escape_string($_POST['SCREENNAME']); //Escape the input data to prevent SQL injection when you query the profanity table.

$ProfanityCheckString = strtoupper($SCREENNAME); //Make the input string uppercase (so that 'BaDwOrD' is the same as 'BADWORD').  All your values in the profanity table will need to be UPPERCASE for this to work.

$ProfanityCheckString = preg_replace('/[_-]/','',$ProfanityCheckString); //I allow alphanumeric, underscores, and dashes...nothing else (I control this with PHP form validation).  Pull out non-alphanumeric characters so 'B-A-D-W-O-R-D' shows up as 'BADWORD'.

$ProfanityCheckString = preg_replace('/1/','I',$ProfanityCheckString); //Replace common numeric representations of letters so '84DW0RD' shows up as 'BADWORD'.

$ProfanityCheckString = preg_replace('/3/','E',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/4/','A',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/5/','S',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/6/','G',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/7/','T',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/8/','B',$ProfanityCheckString);

$ProfanityCheckString = preg_replace('/0/','O',$ProfanityCheckString); //Replace ZERO's with O's (Capital letter o's).

$ProfanityCheckString = preg_replace('/Z/','S',$ProfanityCheckString); //Replace Z's with S's, another common substitution.  Make sure you replace Z's with S's in your profanity database for this to work properly.  Same with all the numbers too--having S3X7 in your database won't work, since this code would render that string as 'SEXY'.  The profanity table should have the "rendered" version of the bad words.

$CheckProfanity = mysql_query("SELECT * FROM DATABASE.TABLE p WHERE p.WORD = '".$ProfanityCheckString."'");
if(mysql_num_rows($CheckProfanity) > 0) {$errors[] = 'Please select another Screen Name.';} //Check your profanity table for the scrubbed input.  You could get real crazy using LIKE and wildcards, but I only want a simple profanity filter.

if (count($errors) > 0) {foreach($errors as $error) {$errorString .= "<span class='PHPError'>$error</span><br /><br />";} echo $errorString;} //Echo any PHP errors that come out of the validation, including any profanity flagging.


//You can also use these lines to troubleshoot.
//echo $ProfanityCheckString;
//echo "<br />";
//echo mysql_error();
//echo "<br />";

我敢肯定,有一种更有效的方法来进行所有这些替换,但是我不够聪明,无法弄清楚(尽管效率低下,这似乎还可以)。

我认为您应该在允许用户注册,并根据需要使用人工过滤和添加到亵渎性表方面犯错。尽管这全都取决于误报(好的单词标记为坏)与误否定(坏单词通过)的成本。最终,这将决定您在过滤策略中有多积极或保守。

如果您要使用通配符,我也会非常小心,因为通配符有时会比您预期的表现更繁琐。


1

坦白说,我会让他们说出“欺骗系统”的话,然后禁止他们,这就是我。但这也使编程更简单。

我要做的是实现一个正则表达式过滤器,如下所示:/[\s]dooby (doo?)[\s]/i或者该词在其他字符之前加上/[\s]doob(er|ed|est)[\s]/。这些将防止过滤像保证一样的单词,这是完全有效的,但是如果您学习新的单词,还需要了解其他变体并更新实际的滤波器。显然,这些都是示例,但是您必须自己决定如何做。

我不会输入我所知道的所有单词,而不是在我实际上不想知道它们时。


1

我同意这个主题是徒劳的,但是如果您需要过滤器,请查看Ning's Boxwood

Boxwood是一个PHP扩展,用于快速替换一段文本中的多个单词。它支持区分大小写和不区分大小写的匹配。它要求对其进行操作的文本编码为UTF-8。

另请参阅此博客文章以了解更多详细信息:

使用Boxwood,您可以根据需要随意设置搜索词的列表-搜索和替换算法不会因为要搜索的单词列表中的单词增多而变慢。它的工作原理是为所有搜索词构建一个trie,然后仅扫描一次主题文本,沿着该trie的元素移动并将它们与文本中的字符进行比较。它支持US-ASCII和UTF-8,区分大小写或不区分大小写的匹配,并具有一些以英语为中心的单词边界检查逻辑。


1

我得出结论,为了创建一个良好的亵渎过滤器,我们需要3个主要组件,或者至少这是我要做的。这些是:

  1. 过滤器:后台服务,可针对黑名单,字典或类似内容进行验证。
  2. 不允许匿名帐户
  3. 报告滥用

红利是一种奖励,以某种方式奖励那些对准确的举报人做出贡献的人,并惩罚犯罪者,例如中止其帐户。


1

也在游戏后期,但是做了一些研究却偶然发现了这里。正如其他人所提到的,如果它是自动化的,那几乎是不可能的,但是如果您的设计/需求在某些情况下(但并非总是如此)涉及人类交互以检查它是否亵渎,您可以考虑使用ML。 https://docs.microsoft.com/zh-cn/azure/cognitive-services/content-moderator/text-moderation-api#profanity是我目前的当前选择,原因有很多:

  • 支持多种本地化
  • 他们不断更新数据库,因此我不必跟上最新的语或语言(维护问题)
  • 当可能性很高(即90%或更高)时,您可以实用地拒绝它
  • 您可以观察导致亵渎或不亵渎旗帜的类别,并可以请他人对其进行审查以告知其亵渎或不亵渎。

出于我的需要,它基于/基于其他用户可能会/将要看到的用户名的公益广告服务(确定,视频游戏),但设计要求它必须经过亵渎性过滤器才能拒绝令人反感的用户名。可悲的是,由于用户名通常是单个单词(最多N个字符),有时是多个单词的串联,因此很可能会出现经典的“ clbuttic”问题。同样,Microsoft的认知服务也不会将“ Assist”标记为Text。 HasProfanity = true,但可以将类别概率之一标记为高。

正如OP所询问的,“ a $$”怎么样,这是我通过过滤器传递的结果:在此处输入图片说明如您所见,它确定它不是亵渎,但很有可能是亵渎,因此标记为推荐评论(人际互动)。

当概率很高时,我可以返回“对不起,这个名字已经被使用”(即使不是),这样它就可以减少对反审查人员的冒犯,如果我们不想的话集成人工审核,或返回“您的用户名已通知现场操作部门,您可以等待用户名被审核和批准,或选择其他用户名”。管他呢...

顺便说一句,出于我的目的,此服务的成本/价格相当低(用户名多久更改一次?),但是对于OP而言,设计可能需要更密集的查询,因此对于支付/订阅而言可能不是理想的选择ML服务,或者不能进行人工审查/交互。一切都取决于设计...但是,如果设计符合要求,也许这可以是OP的解决方案。

如果有兴趣,我可以在以后的评论中列出缺点。


-2

亵渎过滤器是个坏主意。原因是您听不懂每个咒骂词。如果尝试,则会得到假阳性。

流行语

假设您想抓住F字。容易吧?走着瞧。

您可以遍历字符串以查找“ fuck”。不幸的是,当今人们欺骗过滤器。亵渎性的过滤器没有接收到“ fuk”。

您可以尝试检查单词的多种拼写和变体,但这会降低代码的性能。要捕获F字,您需要查找“ fuc”,“ Fuc”,“ fuk”,“ Fuk”,“ F ***”等,然后该列表会一直存在。

避免无罪

好吧,那么如何使其不区分大小写并忽略空格以使其捕获“ F u C k”呢?这听起来像是个好主意,但有人可以通过“ FUCK”绕过亵渎过滤器

您忽略标点符号。

现在这是一个真正的问题,因为像“ 地狱,那里!” 这样的句子 会捡起“地狱”和“ 屁股什么?” 捡起“驴”。

还有就是一堆话,你必须从过滤排除,如“反对针锋相对 ution”,因为它出现的“针锋相对”。

人们还可以使用替代词,例如“ Frack”。你也封锁了吗?那么“ pen is”和“ penis”呢?您的程序没有人工智能来知道字符串的好坏。

不要使用亵渎过滤器。它们很难开发,并且像爬网一样慢。


2
-1不回答OP问题,主要是意见评论。此实用程序有许多有效的用例。例如,在审核前清理源代码,以免公司感到尴尬。
davidjmcclelland

-3

别。

因为:

  • 克洛比蒂奇
  • 亵渎不是OMG邪恶
  • 无法有效定义亵渎
  • 大多数人很可能不喜欢被“保护”免受亵渎

编辑:虽然我同意评论员所说的“审查制度错误”,但这不是答案的本质。


90
10票否决答案?好像有人想要过滤亵渎的话一定是道德上的机智吗?真是的 这是一个有效的问题,过分逼人的驾车反应不应该得到奖励。-1。
克鲁格

12
@Kludge:您是唯一一个说“道德化的机智”的人,实际上我完全没有提到实施亵渎过滤器的道德本质。米奇提出了我说“不”的部分原因,这不是一个狡猾的开车经过。有时“不”是“我如何...?”的正确答案。[续]
失眼

2
@eyelidlessness:也许您是对的,我对您的单个单词答案的阅读过多。但是由于您没有详细说明,所以我无法说出您的反对是出于道德理由还是出于技术理由。我承认我已经厌倦了“任何形式的检查都是不好的”评论。
克鲁格

5
-1。无论道德或技术问题如何,“不要”都不是有效的答案。在很多情况下,根据内容的性质过滤内容非常合适。想象一下一个电子商务网站销售女性内衣并提供“评论”功能。您真的想要青春期前的男孩在您的网站上乱扔垃圾吗?当然不是。可能需要人工批准流程太麻烦了。一个简单的过滤器来拒绝带有垃圾评论的评论是一件好事。
pspahn

3
@pspahn,“不要”是要求解决错误问题的任何问题的正确答案。在某些情况下,当然应该对内容进行审核,但不是“亵渎过滤器”。
眼睑失明
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.