我的博客人气一般,但是垃圾评论却特别之多,严重影响我的心情。自从开博客以来,我一直都是通过 Akismet 插件来发现和过滤垃圾评论,效果非常不错,很少有漏网之鱼。但是前两天在阅读了云淡然同学写的文章wp_create_nonce实现wordpress垃圾评论终极防御之后,我突然萌生出自己写一些阻挡垃圾评论策略的想法。
下面我介绍几条本博客现在正在使用的阻挡垃圾评论的策略,几天下来效果还可以接受。每一种策略都不是完美的,所以只能多种方式配合使用。当然,道高一尺,魔高一丈,很多策略都必须要不断地改进与完善,并且最好根据自己的情况适当地调整。当然,如果你不想折腾,还是老老实实地使用 Akismet 插件来防护吧,插件的功能更加完善可靠,本文的方法只适合于不想启用过多插件和喜欢折腾的同学。
.htaccess 文件
首先我们可以借助 .htaccess 文件来阻挡部分恶意的垃圾评论,这一类评论往往是通过脚本或者工具自动提交的。请将以下内容添加到网站根目录的 .htaccess 文件中:
RewriteEngine On RewriteCond %{REQUEST_METHOD} POST RewriteCond %{REQUEST_URI} .wp-comments-post\.php$ RewriteCond %{HTTP_REFERER} !.*kodango.com.* [OR] RewriteCond %{HTTP_USER_AGENT} ^$ RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]
上面的几条规则,可以阻挡来源不是你博客,或者 user agent 信息为空的机器人评论。
如果有时候某个 ip 或者网段的垃圾评论特别凶猛,也可以将该 ip 或者网段屏蔽掉。例如:
order allow,deny Deny from 123.123.123.123 Deny from 156.156.156.0/24 Deny from 189.189.0.0/16 allow from all
不过,这种方法不是非常推荐,因为很多网站并不是 vps,往往没有独立的 ip 地址,容易造成误杀。
评论黑名单设置
WordPress 本身就带有垃圾评论鉴别的功能,可以在后台"设置-讨论"中配置评论审核和黑名单,每一行是一个关键字,如果评论中出现这些关键字,就会加到评论审核队列,或者直接当作垃圾评论处理。可以将一些明显的推销关键字加到评论黑名单中,这样可以阻挡部分营销推广类型的垃圾评论。
我把自己用的评论黑名单保存在 Gist 上,大家可以参考。
识别垃圾评论
观察了一段时间的垃圾评论,也参考了很多网上流传的比较广的做法,我总结了几条有效地防护策略:
- 如果评论包含黑名单中设置的关键字,则直接丢弃这条评论;
这条策略的前提是黑名单中的关键字是非常明确可靠的,一些模棱两可的关键字请添加到审核列表中。黑名单中的关键字一旦出现,我就认定这条评论是垃圾评论。
- 如果评论中包含日文,则直接丢弃这条评论;
一般我们的博客没有啥国际友人来看,并且还给你留下评论,日本游客就更少了。所以评论中出现日文时,不要手软,直接标记成垃圾评论吧。事实上,我之前的垃圾评论列表中,有50%以上的评论中包含日文。
- 如果评论没有头像,且评论内容中不含中文或者评论字数过多,则标记为垃圾评论;
我一直坚信,有头像的读者是最真诚的,没有头像的读者大多是雁过不留痕,即使留言也不会非常深刻,大多寥寥几语。另外一方面,基本上95%以上的垃圾评论都是不带头像的,而在我这里基本上是100%。所以如果评论者没有头像,在鉴别这条评论是否为垃圾评论时,请更加严格地对待,但也千万不要抱着“宁可错杀一千,也不可放过一个”的想法将没头像的评论全部挡在门外。根据上面的推推断,我在这里加上了是否包含中文,以及字数多少的限制。
- 如果评论有头像或者类型是 pingback/trackback,不含中文且字数过多,则标记为垃圾评论;
流传地很广地一种做法,是将所有不包含中文的评论全部当做垃圾评论,虽然看起来很武断,但是确实最简单高效,前面我也说过,咋博客还真没到走出国门的那一步,不过虽然现实有差距,也可以让我们幻想一下嘛。所以这里我还加上一个评论字数是否过多的判断,如果评论是一长篇洋洋洒洒的英文,不管你信不信,反正我是不信的。
- 如果是普通类型的评论,且评论的 URL过长,则标记为垃圾评论;
我相信大家都会注册一些简洁并且有意义的网站域名,与此相反,垃圾评论留下的 URL 往往没有意义并且很长。
- 如果评论类型是 pingback/trackback,且评论的 URL 中 host 部分长度过长,则标为垃圾评论;
同上,不过因为 pingback/trackback 评论的 URL 是引用你的那篇文章地址,这个地址往往比较长,所以我们这里只管 URL 中的 host 部分。
如果你觉得3、4、5、6中哪一条的识别率很高,达到99%以上,那么也可以将标记为垃圾评论的处理方法,改成直接丢弃该评论,毕竟垃圾评论依然存在数据库中,需要经常清理。
我们将上面梳理的防护策略转换成实际可工作的代码,然后通过 pre_comment_approved
来识别垃圾评论并标记,使用 preprocess_comment
来直接丢弃垃圾评论。
下面是最终的代码:
/* * Get rid of spam comments */ function dangopress_getridof_spam($commentdata) { extract($commentdata, EXTR_SKIP); $nonce = wp_create_nonce($comment_post_ID); /* Check whether the user is in the blacklist */ if (wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent)) { $msg = '您发表的评论中包含被禁止的关键字, 请检查后再评论'; $msg .= ', 点击<a href="' . $_SERVER['HTTP_REFERER'] . '">此处</a>返回'; wp_die($msg); } /* Check whether the comment text contains the japanese chars */ if (preg_match('/[ぁ-ん]+|[ァ-ヴ]+/u', $comment_content)) { wp_die('请勿恶意评论'); } return $commentdata; } add_action('preprocess_comment', 'dangopress_getridof_spam'); /* * Tag spam comments */ function dangopress_tag_spam($approved, $commentdata) { extract($commentdata, EXTR_SKIP); /* Check whether the comment is pingback or trackback */ $is_ping = in_array($comment_type, array('pingback', 'trackback')); /* Parse the author url domain part */ $author_domain = parse_url($comment_author_url, PHP_URL_PATH); /* For pingback/trackback, check the comment author domain length */ if ($is_ping && strlen($domain) > 25) { return 'spam'; } /* For normal comment, check the comment author url length */ if (!$is_ping && strlen($comment_author_url) > 25) { return 'spam'; } /* Check whether there is any chinese words exists */ $has_chinese = preg_match('/[\x{4e00}-\x{9fa5}]+/u', $comment_content); /* Check the comment chars length */ $comment_chars = strlen(trim($comment_content)); if (!$is_ping) { // Normal comment /* Check whether the gravatar exists */ $has_gravatar = dangopress_validate_gravatar($comment_author_email); /* * For normal comment without a gravatar: * * Tag it as spam if no chinese words found, or comment characters are * too many. It's more strict than bellow. */ if (!$has_gravatar && (!$has_chinese || $comment_chars > 120)) { return 'spam'; } } /* * Say too many words without any chinese, tag it spam! */ if (!$has_chinese && $comment_chars > 80) { return 'spam'; } return $approved; } add_filter('pre_comment_approved', 'dangopress_tag_spam', 99, 2);
小伙伴们,赶紧在自己的博客上试试吧~
早上好
喜欢这个风格感谢您。by https://www.jishurenyuan.com
谢谢您的付出真心感谢。
对我很有用谢谢谢。
非常感谢谢谢.
虽然不懂楼主在说什么,但看起来貌似很厉害的样子
没注册限制,确实容易泛滥。当流量上来了,是挡不住垃圾侵袭的。
我直接把 wp-comments-post.php 删了, 只能通过js入口来回复
@牧风:是你们几个博客都在用的 ajax 评论吗?
@kodango:ajax 评论突出一个舒服