你如何实现一个良好的亵渎过滤器?

时间:2008-11-07 20:19:41

标签: php regex user-input multilingual

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

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

是否有可用于包含优秀列表的来源的API?或者也许一个API只是简单地说“是的,这是干净的”或“没有这是脏”的一些参数?

有什么好方法可以让人们试图欺骗系统,例如$$,azz或a55?

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

编辑:对答案的回应,只是避免编程问题:

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

所以我真的指的是弄清楚单个令牌是否脏的方法,然后简单地禁止它。我不打算像完全搞笑的“长颈长颈鹿”参考那样阻止情绪。你无能为力。 :)

21 个答案:

答案 0 :(得分:172)

Obscenity Filters: Bad Idea, or Incredibly Intercoursing Bad Idea?

此外,人们不能忘记The Untold History of Toontown's SpeedChat,即使使用“安全词白名单”,14岁的孩子也会迅速绕过它: “我想把长颈鹿长颈鹿贴在蓬松的白色小兔子身上。”

结论:最终,对于您实施的任何系统,绝对无法替代人工审核(无论是同行还是其他)。随意实现一个基本工具来摆脱驱动器,但对于确定的巨魔,你绝对必须有一个非基于算法的方法。

删除匿名并引入问责制(Stack Overflow功能良好)的系统也很有用,特别是为了帮助打击John Gabriel's G.I.F.T.

您还询问了哪些地方可以获得亵渎性列表以帮助您入门 - 一个要检查的开源项目是Dansguardian - 查看其默认亵渎列表的源代码。还有一个额外的第三方Phrase List,您可以下载代理,这可能是一个有用的收集点。

编辑回复问题编辑:感谢您澄清了您正在尝试做的事情。在这种情况下,如果您只是尝试做一个简单的文字过滤器,有两种方法可以做到。一种是创建一个单一的长正则表达式,其中包含您要审查的所有禁用短语,并且仅使用它进行正则表达式查找/替换。像这样的正则表达式:

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

并使用preg_match()在输入字符串上运行它以批量测试命中,

preg_replace()将其删除。

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

有关其他PHP编程示例,请参阅此页面以获取用于单词过滤的somewhat advanced generic class *来自删失单词的中心字母,此previous Stack Overflow question也有一个PHP示例(主要有价值的部分是基于SQL的过滤词方法 - 如果你觉得不必要,可以省去leet-speak补偿器。

您还添加了:“首先获取单词列表是真正的问题。” - 除了之前的一些Dansgaurdian链接,您可能会发现this handy .zip 458个单词有用。

答案 1 :(得分:39)

虽然我知道这个问题相当陈旧,但这是一个经常出现的问题......

亵渎过滤器有一个原因和一个明显的需求(见Wikipedia entry here),但由于非常不同的原因,它们往往达不到100%的准确性; 上下文准确性

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

用户生成的内容不仅包含潜在的咒骂词,还包含令人反感的引用:

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

可能还有多种语言。迄今为止,Shutterstock已经用10种语言开发了basic dirty-words lists,但它仍然是基本的,并且非常注重其“标记”需求。网上还有许多其他列表。

我同意接受的答案,即它不是一个定义的科学, 语言是一个不断发展的挑战,但90%的捕获率优于0% 。这完全取决于你的目标 - 你想要达到的目标,你所拥有的支持程度以及删除不同类型亵渎的重要性。

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

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

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

基本过滤器包含:

  • 建立适用亵渎的清单
  • 开发一种处理亵渎衍生物的方法

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

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

复杂的过滤器会涉及以下一些内容(除了适度的过滤器):

答案 2 :(得分:26)

我不知道有什么好的图书馆,但无论你做什么,都要确保你犯错误的方向。我处理的系统不允许我使用“mpassell”作为用户名,因为它包含“ass”作为子字符串。这是疏远用户的好方法!

答案 3 :(得分:23)

在我的面试中,正在采访我的公司CTO试用了我用Java编写的单词/网页游戏。在整个牛津英语词典的单词列表中,第一个出现在猜测的词是什么?

当然,英语中最含糊的词。

不知何故,我仍然得到了工作机会,但我随后找到了一个亵渎词汇表(不是unlike this one)并编写了一个快速脚本来生成一个没有所有坏词的新词典(甚至没有看看清单。)

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

答案 4 :(得分:21)

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

说,任何“淘气词”列表都可能与其他列表一样好,因为基本问题是语言理解,这对当前技术来说几乎是难以处理的

所以,唯一可行的解​​决方案是双重的:

  1. 准备经常更新您的词典
  2. 雇用一名人工编辑来纠正误报(例如“clbuttic”而不是“classic”)和假阴性(oops!错过了一个!)

答案 5 :(得分:13)

答案 6 :(得分:13)

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

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

答案 7 :(得分:7)

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

更大的挑战是提出一些让人们能够引用“强大而不是剑”的东西,同时阻止“e s”。

答案 8 :(得分:7)

谨防本地化问题:在一种语言中,什么是脏话可能在另一种语言中是一个完全正常的词。

目前的一个例子:ebay使用字典方法从反馈中过滤“坏词”。如果你试图输入“这是一个完美的交易”(“das war eine perfekte Transaktion”)的德语翻译,ebay将拒绝由于不良词汇引起的反馈。

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

请注意本地化问题。

答案 9 :(得分:6)

如果您可以执行类似Digg / Stackoverflow的操作,用户可以在其中投票/标记淫秽内容......请执行此操作。

然后您需要做的就是检查“顽皮”用户,如果他们违反规则就阻止他们。

答案 10 :(得分: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>

结果

  

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

答案 11 :(得分:2)

别。它只会导致问题。我用亵渎过滤器获得的一个个人经验就是我从IRC频道被踢/被禁止的时间,因为我提到我“正在过桥到汉考克几个小时”或类似的事情。

答案 12 :(得分:2)

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

另一方面,虽然其他人正在辩论审查制度的道德规范,但我必须同意在网络上需要某种形式。有些人只是喜欢发布粗俗,因为它可能立即冒犯大量的人,并且绝对不需要作者的思考。

感谢你的想法。

HanClinto规则!

答案 13 :(得分: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 />";

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

我认为您应该允许用户注册,并使用人工过滤并根据需要添加到您的亵渎表中。虽然这一切都取决于假阳性的成本(好的词被标记为坏)而不是假阴性(坏词通过)。这应该最终决定你在过滤策略中的积极性或保守性。

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

答案 14 :(得分:2)

我用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,并在用户输入内容时进行检查。

答案 15 :(得分:1)

我同意这个主题是徒劳的,但如果你必须有一个过滤器,请查看Ning的Boxwood

  

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

另请参阅此博客文章了解更多详情:

  

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

答案 16 :(得分:1)

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

  1. 过滤器:验证黑名单,字典或类似内容的后台服务。
  2. 不允许匿名帐户
  3. 举报滥用行为
  4. 奖金,它将以某种方式奖励那些为准确滥用记者做出贡献并惩罚犯罪者的人,例如:暂停他们的帐户。

答案 17 :(得分:1)

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

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

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

答案 18 :(得分:0)

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

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

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

OP询问“ a $$”如何,这是我通过过滤器传递的结果:enter image description here,如您所见,它确定它不是亵渎行为,但可能性很高确实如此,因此标记为审查(人际互动)的建议。

当概率很高时,我可以返回“对不起,这个名字已经被使用”(即使不是),这样如果我们不这样做的话,它对反审查人员或其他事物的攻击性就会降低不想集成人工审核,或返回“您的用户名已通知现场运营部门,您可以等待用户名被审核和批准或选择其他用户名”。或其他...

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

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

答案 19 :(得分:-2)

亵渎过滤器是一个坏主意。原因是你不能抓住每个发誓的话。如果你尝试,你会得到假阳性。

捕捉单词

我们只想说你想抓住F-Word。容易,对吗?好吧,让我们看看。

你可以循环一个字符串来找到&#34;他妈的。&#34;不幸的是,人们现在使用过滤器。亵渎过滤器没有找到&#34; fuk。&#34;

可以尝试检查单词的多个拼写和变体,但这会降低代码的性能。要抓住F-Word,你需要寻找&#34; fuc&#34;,&#34; Fuc&#34;,&#34; fuk&#34;,&#34; Fuk&#34;,&# 34; F ***&#34;等等。列表一直在继续。

避免无罪

好吧,那么如何让它不区分大小写并忽略空格,以便它能够捕获&#34; F u C k&#34;?这可能听起来是个好主意,但有人可以绕过亵渎过滤器&#34; F.U.C.K。&#34;

你忽略了标点符号。

现在这是一个真正的问题,因为像&#34; Hell o这样的句子,就在那里!&#34;会接受#34;地狱,&#34;和&#34; Wh 屁股 up?&#34;选择&#34; ass。&#34;

还有一堆你必须从过滤器中排除的单词,例如&#34; Cons tit ution,&#34;因为有&#34; tit&#34;在它。

人们也可以使用替代词,例如&#34; Frack。&#34;你也阻止了吗?怎么样&#34;笔是&#34;对于&#34;阴茎&#34;?你的程序没有人工智能来知道字符串是好还是坏。

不要使用亵渎过滤器。他们很难发展,而且他们像爬行一样慢。

答案 20 :(得分:-3)

别。

由于:

  • Clbuttic
  • 亵渎不是OMG EVIL
  • 亵渎无法有效定义
  • 大多数人很可能不喜欢受到“亵渎”的保护

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