推文排除

时间:2011-02-24 07:25:56

标签: ruby-on-rails ruby twitter

让我们假设我有一个用户创建主题并在Fruit上编写主题的网站。

为了让用户了解整个网络上的所有水果对话,我会收集与特定主题相关的推文,并根据推文内容创建主题。

显然,推文与主题相关非常重要。假设用户创建了一个名为Apples和Oranges的主题。我拉所有包含关键词Apples和/或Oranges的推文。

我遇到的问题是,一些Twitter用户编写了一条推文,其中包含关键词Apples,Oranges,Pears等,并将其收集并作为线程发布到Apples和Oranges讨论主题。这让用户生气了!

所以我需要的是一种过滤任何包含除苹果​​和/或橘子以外的水果单词的推文的方法。

例如,如果Twitter用户写道“我喜欢苹果,橘子,梨子和葡萄”,则不应包含该推文。

现在,您只能使Twitter搜索查询变得如此复杂。因此,在收集推文后,必须在Ruby中执行排除逻辑。

以编程方式,您将如何解决这个问题?

5 个答案:

答案 0 :(得分:7)

确定与主题名称相关的单词。梨,葡萄等。然后您可以排除使用这些相关单词的推文。

一种方法是使用Google Sets。

注意:我处于不完全宽容我自己的解决方案的不幸位置,因为这项服务没有官方API(就像这样真棒!)。虽然你打算去使用此策略然后我建议存储Google Set结果。

require 'google_set'

twitter_search_terms = ['apples', 'oranges']
# Mocked twitter search method
tweets = search_twitter(twitter_search_terms)
# returns ["Both apples and oranges are great!", "I love Apples, Oranges, Pears, and Grapes."]

related_words = GoogleSet.for(*twitter_search_terms)
# returns ["apples", "oranges", "bananas", "peaches", "pears", "grapes", "strawberries", "plums", ...]
related_words = (related_words - twitter_search_terms).each(&:downcase)

good_tweets = []
bad_tweets = []
tweets.each do |tweet|
  tweet_words = tweet.downcase.split
  # Remove any non-word characters
  tweet_words = tweet_words.map { |word| word.gsub(/\W+/, '') }.compact

  if (tweet_words - related_words).size == tweet_words.size
    good_tweets << tweet
  else
    bad_tweets << tweet
  end
end

p good_tweets
# returns ["Both apples and oranges are great!"]

p bad_tweets
# returns ["I love Apples, Oranges, Pears, and Grapes."]

答案 1 :(得分:1)

class Fruit < AR::Base
  has_many :tweets
end

class Tweet < AR::Base
  belongs_to :fruit

  # validation catches any tweets that mention more than one fruit
  def validate
    self.errors[:base] = 'Mentions too many fruit' unless single_topic?
  end

  def single_topic?
    Fruit.count(:conditions => {:name => words).eql?(1)
  end

  # if validation passes the the fruit is parsed
  before_create :parse_fruit_from_text

  def parse_fruit_from_text
    self.fruit_id = Fruit.first(:conditions => {:name => words}, :select => 'id').id
  end

  def words
    @words ||= this.text.split(' ')
  end

end

# Now you can just do...
Tweet.create(json)

您需要考虑与Fruit#名称的案例差异。我建议将所有名称保存为小写,然后将所有查询下载。您还可以使用LOWER编写自定义SQL查询。

答案 2 :(得分:0)

是的,你应该在Ruby中这样做。在找到推文后,请确保它不包含搜索关键字以外的任何关键字。因此,如果您通过搜索“Apple”找到推文,则应确保它不包含其他(N-1)关键字,如Orange,Grapes等。

或者,您可以将推文拆分为单词,然后确保没有任何单词与您的关键字匹配,但搜索的除外。这将更快,因为推文可能只包含比您的关键字数量更少的单词。

答案 3 :(得分:0)

看一下Ruby Classifier gem。

答案 4 :(得分:0)

作为补充建议,考虑到您的网站可能实际上并不是关于水果,您可以通过绘制用户在您网站上创建的其他群组来决定要排除哪些关键字。

例如,如果有人创建了一个“苹果”组并且其他人创建了一个“橘子”组,那么关于“苹果和橘子”的推文将无法正确显示,但有关橘子和金橘的推文会正确显示在橘子队的线索,直到有人为金橘组成一个小组。