214

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

在哪里可以找到各种语言和方言的脏话列表?

是否有可用于包含良好列表的来源的 API?或者可能是一个 API 简单地说“是的,这是干净的”或“不,这是脏的”,带有一些参数?

有什么好的方法可以抓住试图欺骗系统的人,比如 a$$、azz 或 a55?

如果您提供 PHP 解决方案,则可获得奖励积分。:)

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

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

所以我真的指的是一种方法来确定单个令牌是否脏,然后简单地禁止它。我不会费心阻止像完全热闹的“长颈长颈鹿”参考这样的情绪。你在那里无能为力。:)

4

20 回答 20

181

淫秽过滤器:坏主意,还是令人难以置信的相互交流的坏主意?

此外,人们不能忘记Toontown 的 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很有帮助。

于 2008-11-07T20:21:12.833 回答
48

虽然我知道这个问题已经相当老了,但这是一个常见的问题......

对脏话过滤器既有原因也有明显的需求(请参阅此处的 Wikipedia 条目),但由于非常明显的原因,它们通常不能 100% 准确;上下文准确性

这(完全)取决于你想要达到的目标——在最基本的情况下,你可能试图掩盖“七个肮脏的词”,然后……有些企业需要过滤最基本的亵渎:基本脏话、网址甚至个人信息等,但其他人需要防止非法帐户命名(Xbox live 就是一个例子)或者更多......

用户生成的内容不仅包含潜在的脏话,还可能包含对以下内容的冒犯性引用:

  • 性行为
  • 性取向
  • 宗教
  • 种族
  • ETC...

并且可能会使用多种语言。迄今为止, Shutterstock 已经开发了 10 种语言的基本脏词列表,但它仍然是基本的,并且非常面向他们的“标记”需求。网络上还有许多其他列表。

我同意公认的答案,即它不是一门明确的科学,因为语言是一个不断发展的挑战,但 90% 的捕获率优于 0%。这完全取决于你的目标——你想要达到的目标、你所拥有的支持水平以及消除不同类型的亵渎行为的重要性。

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

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

您可以轻松构建一个能够捕获 90% 以上的脏话的脏话过滤器,但您永远不会达到 100%。这是不可能的。越接近 100%,就越难……在过去构建了一个复杂的亵渎引擎,每天处理超过 50 万条实时消息,我提供以下建议:

基本过滤器将涉及:

  • 建立适用的脏话列表
  • 开发处理亵渎派生的方法

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

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

一个复杂的过滤器将涉及以下一些(除了中等过滤器):

于 2012-11-19T04:27:21.010 回答
29

我不知道有什么好的库可以解决这个问题,但无论你做什么,都要确保你在让东西通过的方向上犯了错误。我处理过不允许我使用“mpassell”作为用户名的系统,因为它包含“ass”作为子字符串。这是疏远用户的好方法!

于 2008-11-07T20:26:00.903 回答
24

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

也就是说,任何“淘气词”列表的性能都可能与其他列表一样好,因为潜在的问题是语言理解,这对于当前的技术来说非常棘手

因此,唯一实用的解决方案是双重的:

  1. 准备好经常更新你的字典
  2. 聘请人工编辑来纠正误报(例如“clbuttic”而不是“经典”)和误报(哎呀!错过了一个!)
于 2008-11-07T22:27:08.943 回答
24

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

当然是英语中最脏的词。

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

对于您的特定情况,我认为将搜索与真实单词进行比较听起来像是使用这样的单词列表的方式。替代样式/标点符号需要更多的工作,但我怀疑用户会经常使用它来成为一个问题。

于 2008-11-07T22:36:23.653 回答
14

防止冒犯性用户输入的唯一方法是阻止所有用户输入。

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

于 2008-11-07T20:42:39.200 回答
13

看看CDYNE 的亵渎过滤器 Web 服务

测试网址

于 2008-11-07T20:27:24.317 回答
8

注意本地化问题:在一种语言中是脏话,在另一种语言中可能是完全正常的词。

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

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

所以要注意本地化问题。

于 2010-04-27T12:55:55.407 回答
7

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

更大的挑战是想出一些东西,让人们引用“比剑更强大”,同时阻止“阴茎”。

于 2008-11-08T01:35:13.167 回答
7

我收集了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 执行到您的数据库中,并在每次用户输入内容时进行检查。

于 2017-03-03T08:22:10.967 回答
6

如果您可以执行 Digg/Stackoverflow 之类的操作,用户可以在其中投票/标记淫秽内容……请这样做。

然后你需要做的就是审查那些“淘气”的用户,如果他们违反了规则就阻止他们。

于 2008-11-07T20:46:59.007 回答
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>

结果

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

于 2012-10-29T03:22:52.477 回答
3

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

  • 支持多种本地化
  • 他们不断更新数据库,所以我不必跟上最新的俚语或语言(维护问题)
  • 当概率很高(即 90% 或更多)时,您可以务实地否认它
  • 您可以观察导致标记可能是或可能不是亵渎的类别,并且可以让某人对其进行审查以教导它是否亵渎。

根据我的需要,它是/基于公共友好的商业服务(好的,视频游戏),其他用户可能/将会看到用户名,但设计要求它必须通过亵渎过滤器来拒绝冒犯性的用户名。可悲的是,很可能会发生经典的“clbuttic”问题,因为用户名通常是单个单词(最多 N 个字符),有时是多个单词连接在一起......同样,Microsoft 的认知服务不会将“Assist”标记为文本。 HasProfanity=true 但可能将其中一个类别的概率标记为高。

正如 OP 询问的那样,“a$$”怎么样,这是我通过过滤器时的结果:在此处输入图像描述如您所见,它已确定它不是亵渎神灵,但它很有可能是,所以标记为推荐审查(人际互动)。

当概率很高时,我可以返回“对不起,那个名字已经被占用了”(即使不是),这样如果我们不想的话,它对反审查人员或其他东西的冒犯性就会降低集成人工审核,或返回“您的用户名已通知直播运营部门,您可以等待您的用户名审核通过或选择其他用户名”。管他呢...

顺便说一句,就我的目的而言,这项服务的成本/价格非常低(用户名多久更改一次?),但同样,对于 OP,设计可能需要更密集的查询,并且可能不适合付费/订阅ML 服务,或者不能进行人工审查/交互。这一切都取决于设计......但如果设计确实符合要求,也许这可以成为 OP 的解决方案。

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

于 2019-04-25T16:47:47.050 回答
2

我同意 HanClinto 在本次讨论中较高的帖子。我通常使用正则表达式来匹配输入文本。这是徒劳的,因为,就像您最初提到的那样,您必须在“阻止”列表中明确说明网络上流行的每种写作技巧形式。

在旁注中,当其他人在争论审查制度的伦理时,我必须同意某种形式在网络上是必要的。有些人只是喜欢张贴粗俗,因为它可以立即冒犯一大群人,并且绝对不需要作者考虑。

谢谢你的想法。

汉克林托规则!

于 2009-02-24T20:30:20.737 回答
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 />";

我确信有一种更有效的方法来完成所有这些替换,但我不够聪明,无法弄清楚(这似乎工作正常,尽管效率低下)。

我认为您应该在允许用户注册方面犯错,并根据需要使用人工过滤并添加到您的亵渎表中。尽管这一切都取决于误报(好的词被标记为坏词)与误报(坏词通过)的成本。这应该最终决定您在过滤策略中的激进或保守程度。

如果你想使用通配符,我也会非常小心,因为它们有时会比你想要的更繁重。

于 2011-08-16T02:33:47.447 回答
1

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

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

我不打算打出我知道的所有单词,而不是在我实际上不想知道它们的时候。

于 2008-11-07T20:25:28.860 回答
1

不。它只会导致问题。我对亵渎过滤器的一次个人经历是我被 IRC 频道踢/禁止的时间,因为我提到我“要过桥去汉考克几个小时”或类似的东西。

于 2008-11-07T20:37:46.777 回答
1

我同意这个主题的徒劳,但如果你必须有一个过滤器,看看宁的黄杨木

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

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

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

于 2010-09-30T09:01:18.970 回答
1

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

  1. 过滤器:根据黑名单、字典或类似的东西进行验证的后台服务。
  2. 不允许匿名帐户
  3. 报告滥用

奖金,它将以某种方式奖励那些提供准确滥用报告的人并惩罚违规者,例如暂停他们的帐户。

于 2012-10-12T02:51:31.847 回答
-8

不。

因为:

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

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

于 2008-11-07T20:22:31.567 回答