【问题标题】:Continuing get request from where it left off after hitting rate limit?在达到速率限制后继续从中断的地方获取请求?
【发布时间】:2014-07-15 05:50:49
【问题描述】:

我找到了一个脚本,可以用来创建一个推特用户关注的所有人的列表(在本例中为“@kingjames”)。曾经有一个私有方法 next_cursor 在 Twitter API 中以某种方式公开,但现在它真的是私有的,因为我无法调用它,如果我尝试它会引发错误。

删除下面脚本中对next_cursor 的所有引用会消除错误消息,但脚本无法开始添加用户。由于停止时的速率限制,该脚本必须暂停 15 分钟,因此它一遍又一遍地添加相同的用户。

您能否建议一种方法来更改脚本以使其从中断处继续,从而不会一遍又一遍地添加相同的用户?

 #!/usr/bin/env ruby
 require 'rubygems'
 require 'twitter'



def fetch_all_friends(twitter_username, max_attempts = 100)
  # in theory, one failed attempt will occur every 15 minutes, so this could be long-running
  # with a long list of friends
  num_attempts = 0
  client = client = Twitter::REST::Client.new do |config|
  config.consumer_key     = "8nwjpoIsqag..."
  config.consumer_secret  = "Wj20rZEfPsyHd0KnW..."
  config.access_token     = "363090951-n5NdXfp5wWCkNU5eY..."
  config.access_token_secret = "7eydU2nQHMsSVB8W76Z2PKH1P...."
end

  myfile = File.new("#{twitter_username}_friends_list.txt", "w")
  running_count = 0
  cursor = -1
  while (cursor != 0) do
    begin
      num_attempts += 1
      # 200 is max, see https://dev.twitter.com/docs/api/1.1/get/friends/list
      friends = client.friends(twitter_username, {:cursor => cursor, :count => 200} )
      # friends = client.friends(twitter_username ).take(200) //seems like another way to get 200 users
      friends.each do |f|
        running_count += 1
        myfile.puts "\"#{running_count}\",\"#{f.name.gsub('"','\"')}\",\"#{f.screen_name}\",\"#{f.id}\""
      end
      puts "#{running_count} done"
      # cursor = friends.next_cursor
      # break if cursor == 0
    rescue Twitter::Error::TooManyRequests => error
      if num_attempts <= max_attempts
        # cursor = friends.next_cursor if friends && friends.next_cursor
        puts "#{running_count} done from rescue block..."

        puts "Hit rate limit, sleeping for #{error.rate_limit.reset_in}..."
        sleep error.rate_limit.reset_in
        retry
      else
        raise
      end
    end
  end
end

fetch_all_friends("kingjames")

【问题讨论】:

  • 我刚刚写了一篇博文,介绍如何使用 Yelp api here 做到这一点。让我看看它是否也适用于 Twitter
  • @anthony 好的,谢谢,请尽可能回复
  • 诀窍是不要达到极限。通过故意在循环之间休眠来限制您的代码,或者找到一种方法来分解查询并在达到预定限制时暂停。爆破请求并达到限制并不是一个好的网络公民,所以学习如何让你的代码表现得更好。

标签: ruby twitter


【解决方案1】:

曾经有一个私有方法 next_cursor 以某种方式公开 在 Twitter api 中,但现在它真的是私有的,因为你不能调用 如果您尝试,它会引发错误。

ruby 对调用私有方法没有限制。唯一的限制是在调用私有方法时不能显式指定接收者。这是一个例子:

class Dog
  private
  def next_cursor
    puts "I'm the next cursor."
  end
end


friends = Dog.new
friends.next_cursor

--output:--
1.rb:10:in `<main>': private method `next_cursor' called for #<Dog:0x00000100a40fc8> (NoMethodError)

friends.instance_eval do
  next_cursor   #You can't explicitly specify a receiver for a private method, 
                #and ruby uses whatever object is self as the receiver
end

--output:--
I'm the next cursor.

如果您不了解 Ruby 的来龙去脉,那么该代码会显得相当混乱。但是 Ruby 也提供了一个名为 send() 的方法,它允许你调用任何方法:

friends.send(:next_cursor)

--output:--
I'm the next cursor.

【讨论】:

  • 实际上这是有道理的,但你不能在这行代码中使用send() 你能cursor = friends.next_cursor if friends &amp;&amp; friends.next_cursor 如何解决这里访问私有方法 next_cursor 的需要(因为这是一部分我需要使用的脚本)
  • 我要试试这个cursor = friends.send(:next_cursor) if friends &amp;&amp; friends.send(:next_cursor)
  • @Leachim,你在救援条款中的条件很古怪cursor = friends.next_cursor if friends &amp;&amp; friends.next_cursor。这可能最终会调用 next_cursor() 两次,并且只需要调用一次 next_cursor() 会更有效:cursor = friends.send(:next_cursor); if friends and cursor ....#do something
  • 我正在尝试做同样的事情,但不明白这个脚本是如何工作的,谁能帮助我?如果有必要我会问一个问题。 @7stud
  • @marriedjane875,您在理解哪个方面有困难:send() 或 instance_eval()?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多