最近公园网站开启匿名评论之后,垃圾评论就一直是一个让人头疼的问题。关键词过滤及限制评论数很容易被找到针对的办法,发垃圾评论的人会不停的通过空格,符号等来绕过关键词的过滤。对于一个每天评论不过百的网站来说,上 NLP 又太重了 (其实是不懂).
后来我想到公园网站的垃圾评论大部分内容都是几个垃圾评论的变种,内容的相似度都比较高。所以我只需要维护一个包含这几个内容的列表,并计算语句的相似度,屏蔽掉相似度较高的评论就可以暂时达到过滤垃圾评论的目的。
研究如何计算过程中我找到了 2 种方式,Levenshtein distance 以及 How to Strike a Match . 最后我使用了后者计算相似度的方式实现了一个简单的评论过滤系统。
text这个 gem 同时提供了以上两种算法。有兴趣的可以看一下源码中两种算法的具体实现。
Comment 中验证评论是否合法
class Comment < ActiveRecord::Base
...
validate :check_spam
...
def check_spam
#遍历检查 spam 中条目与评论的相似度, 如果大于设定比例则添加 error, 验证失败
Spam.all.each do |spam|
if Text::WhiteSimilarity.new.similarity(body, spam.body) > (spam.similarity || 0.9)
errors.add(:body, "内容不合法")
return
end
end
# 对于 spam 中没有收录的模板或漏网之鱼的新评论检查与最近的3条评论的相似度
# 如果相似度大于95%则过滤, 一般垃圾评论都是连续刷评论的.
new_record? and Comment.last(3).each do |comment|
if Text::WhiteSimilarity.new.similarity(body, comment.body) > 0.95
errors.add(:body, "内容不合法")
return
end
end
end
end
加上这层防护之后,应该可以暂时安心了。