分享 一个简单的评论过滤系统的实现

flypiggys · 2015年01月14日 · 最后由 davidzhu001 回复于 2015年03月12日 · 8967 次阅读
本帖已被设为精华帖!

最近公园网站开启匿名评论之后, 垃圾评论就一直是一个让人头疼的问题. 关键词过滤及限制评论数很容易被找到针对的办法, 发垃圾评论的人会不停的通过空格, 符号等来绕过关键词的过滤. 对于一个每天评论不过百的网站来说, 上 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

加上这层防护之后, 应该可以暂时安心了.

原文连接

通过相似度,屌!

还有土一点的方法,discuz 的实现方案,http://wikimo.net/blogs/616/, 比如敏感词 “毒{5}品”,类似,“毒 X 品,毒 XX 品,毒 XXX 品……” 5 个区间大小都能匹配到,然后自己维护一套敏感词库;思路相对简单

我想的都太低端了,曾经想过维护一个关键词的列表、用户拉黑等等都不太起作用,看到楼主的这个感觉简直碉堡了!赞赞赞!

有个插件 harmonious_dictionary

点赞 :plus1:

还有个插件叫 similar_text,随手找了点儿数据测了一下 text 的 White similarity 稍慢一点点…

#8 楼 @jimrokliu 😂 😂准备试着换贝叶斯了......昨天又被垃圾评论教育了一回.回头更新下我被教育的经历.....

点赞 :plus1:

瞄了一眼公式,原来用的 dice 系数。 我觉得可以有一种比较靠谱的实现方法。我来说一下思路。

1.收集大量垃圾评论。 2.分析大量垃圾评论的特点,为这些特点设计特征函数。上面的 dice 系数也可以作为一个特征。再比如垃圾评论的长度也可以是一个特征。另外一些上下文也可以是特征。总之越多越好。 3.用特征函数的 vector 表示每一条收集垃圾评论。 4.利用二值分类器 (svm 之类) 批量学习垃圾评论,生成一个垃圾评论识别器。 5.将每一条新发表的评论作为识别器的输入,识别器自动识别垃圾评论与否。

#12 楼 @gyorou 用贝叶斯就够了,效果也足够好…… svm 太麻烦了……

楼上的方案都好高大上,好好学习,哈哈

仅且只有贝叶斯定理,和判断垃圾邮件是一样的道理.

赞 ,这样方便多了~

学习了:thumbsup:

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册