5

假设“xyza”是一个坏词。我正在使用以下方法来替换冒犯性的话-

$text = str_replace("x***","(Offensive words detected & removed!)",$text);

此代码会将 xyza 替换为“(检测到并删除冒犯性词语!)”。

但是如果有人键入 XYZA 我的代码无法检测到它,问题就是“案例”。如何解决?

4

6 回答 6

11

无论您做什么,用户都会找到绕过您的过滤器的方法。它们将使用 unicode 字符(аss例如,使用西里尔字母а并且不会被任何正则表达式解决方案捕获)。他们将使用空格、美元符号、星号,以及您尚未设法捕捉到的任何内容。

如果家庭友好对您的应用程序至关重要,请在内容上线之前让人员对其进行审核。否则,请添加标记功能,以便其他人可以标记攻击性内容。更好的是,使用某种机器学习或贝叶斯过滤器来自动标记潜在的攻击性帖子并让人们手动检查它们。人们比计算机更好地阅读人类语言。

于 2013-08-21T08:12:39.403 回答
3

白名单/黑名单的问题是——正如其他用户所指出的——你的用户会优先考虑找到绕过你的过滤器的方法以获得满意,而不是使用你的网站来达到它的目的,不管它可能是什么。

一种方法是使用谷歌为其“你喜欢什么?”创建的无证亵渎 API。网站。如果您收到回复,true只需给用户一条消息,说明由于检测到亵渎内容而无法提交他们的帖子。

您可以按如下方式处理:

<?php

if (isset($_POST['submit'])) {
    $result = json_decode(file_get_contents(sprintf('http://www.wdyl.com/profanity?q=%s', urlencode($_POST['comments']))));
    if ($result->response == true) {
        // profanity detected
    }
    else {
        // save comments to database as normal
    }
}
于 2013-08-21T11:35:43.940 回答
2

其他答案和评论说编程不是这个问题的最佳解决方案。我同意他们。这些答案应该转移到版主 - Stack Exchange网站管理员 - Stack Exchange

由于这是stackoverflow,我的答案将基于计算机编程。

如果您想使用 str_replace,请执行以下操作。为了这篇文章,由于有些人被实际的 cusswords 冒犯了,让我们假装这些是坏词:'fug'、'schnitt'、'dam'。

$text = str_ireplace(" fug ","(Offensive words detected & removed!)",$text);

注意,str_ireplace不是str_replacei表示“不区分大小写”。但这会错误地匹配“fuggedaboudit”,例如。

如果你想做一个更可靠的工作,你需要使用正则表达式。

$bad_text = "Fug dis schnitt, because a schnitter never dam wins a fuggin schnitting darn";
$hit_words = array("fug","schnitt","dam"); // these words are 'hits' that we need to replace. hit words...
array_walk($hit_words, function(&$value, $key) { // this prepares the regex, requires PHP 5.3+ I think.
  $value = '~\b' . preg_quote( $value ,'~') . '\b~i'; // \b means word boundary, like space, line-break, period, dash, and many others. Prevends "refudgee" from being matched when searching for "fudge"
});

/*print_r($bad_words);*/
$good_words = array("fudge","shoot","dang");

$good_text = preg_replace($hit_words,$good_words,$bad_text); // does all search/replace actions at once

echo '<br />' . $good_text . '<br />';

这将一次完成所有搜索/替换。这两个数组应该包含相同数量的元素,匹配搜索和替换词。它不会匹配部分单词,只会匹配整个单词。当然,坚定的咒骂者会想方设法将他们的脏话传到您的网站上。但它会阻止懒惰的诅咒者。

我决定添加一些指向显然使用编程通过删除亵渎进行第一次运行的网站的链接。当我遇到它们时,我会添加更多。除了雅虎:

1.) Dell.com - 将匹配词替换为<profanity deleted>. http://en.community.dell.com/support-forums/peripherals/f/3529/t/19502072.aspx

2.) 超级计算机沃森显然出现了一个诅咒问题。您如何区分诅咒和俚语?显然,这太难了,研究人员刚刚决定将其全部清除。但他们可能只是使用了一个诅咒词列表(我想说完全匹配是正则表达式的一个子集)并禁止使用它们。无论如何,这就是它在现实生活中的运作方式。 沃森出现了亵渎问题

3.) Apps for Business 中 Gmail 自定义设置的内容合规性部分:

  1. 添加描述您要在每条消息中搜索的内容的表达式

使用的“表达式”可以有多种类型,包括“高级内容匹配”,除其他外,它允许您选择“匹配类型”选项,与您在 excel 过滤器中的选项非常相似:开始于,结束with、Contains、Not contains、Equals、Is Empty,想必都是使用Regex。但是等等,还有更多:匹配正则表达式,不匹配正则表达式,匹配任何单词,匹配所有单词。因此,强大的 Google 为其业务用户实施了正则表达式过滤选项。当正则表达式被认为如此无效时,它为什么会这样做?因为它实际上已经足够有效了。这是一个简单、快速的编程解决方案,只有当人们一心想规避它时才会失败。

除了这个列表,我想知道是否还有其他人注意到清除亵渎和过滤垃圾邮件之间的相似之处。显然,正则表达式在这两个领域都有用,但是如果甚至提到正则表达式,那些死记硬背“所有正则表达式都是坏的”的挑剔者总是会否决任何问题的答案。尝试谷歌搜索“垃圾邮件过滤器的工作原理”。你会得到这样一个涵盖垃圾邮件刺客的结果: http ://www.seas.upenn.edu/cets/answers/spamblock-filter.html

我确定使用正则表达式的另一个示例是通过 Amazon.com 的 Amazon Marketplace 进行通信时。您会通过常用的电子邮件地址接收电子邮件。因此,自然地,在回复卖家时,您的电子邮件程序将包含各种发件人信息,例如您的电子邮件地址、抄送电子邮件地址以及您在正文中输入的任何信息。但 Amazon.com 删除了这些“以保护您”。我能找到绕过这个正则表达式的方法吗?可能,但它会花费更多的麻烦而不是它的价值,因此在一定程度上是有效的。他们还将电子邮件保留 2 年,大概是为了在出现任何欺诈索赔时人们可以检查它们。

SpamAssassin 还会查看邮件的主题和正文,以了解人们在邮件“看起来像垃圾邮件”时注意到的相同类型的内容。它搜索诸如“伟哥”、“立即购买”、“最低价格”、“点击这里”等字符串。它还搜索华丽的 HTML,如大字体、闪烁的文本、鲜艳的颜色等。

没有提到正则表达式,但我确定它正在使用中。

于 2013-08-21T07:53:01.993 回答
0

使用“str_ireplace”替换任何区分大小写的字符串可能,这将帮助你

$text = 'contains offensive_word .... so on';
$array = array(
  'offensive_word' => '****',
  'offensive_word2' => '****',
  'offensive_word3' => '****',
 //.....
);
$text = str_ireplace(array_keys($array),array_values($array), $text);
echo $text;
于 2013-08-21T08:08:59.360 回答
0

使用不区分大小写的 str_replace() 版本的str_ireplace函数

$text = str_ireplace("flip","(Offensive words detected & removed!)", $text);
于 2013-08-21T07:48:49.180 回答
0

您应该使用正则表达式替换,并且需要将i标志添加到正则表达式的末尾,以便它搜索您的文本而不管大小写。所以..

$text = preg_replace("/xyza/i","(Offensive words detected & removed!)", $text);

str_ireplace如果您不需要复杂的正则表达式规则,也可以使用。

$text = str_ireplace("xyza","(Offensive words detected & removed!)", $text);

事实上,后者是首选方式,因为它比正则表达式操作更快。来自 PHP 文档:

如果您不需要花哨的替换规则,通常应该使用此函数而不是带有 i 修饰符的 preg_replace()。

但是,正如评论者指出的那样,如果您要替换的子字符串作为另一个非冒犯性单词的一部分出现,简单的字符串/正则表达式替换可能会破坏您的字符串。为此,您可以在正则表达式中使用单词边界或仅替换那些不能成为其他字符串一部分的单词(例如 word xyza)。

于 2013-08-21T08:02:17.657 回答