Twitter APIリミットでrescueに返されるerrorオブジェクト

Twitter APIリミットの残存回数取得メソッド - 別館 子子子子子子(ねこのここねこ)の続きです。
Twitter APIへアクセスしているときに、上限に達するとTooManyRequestsエラーになります。当然です。
そのTooManyRequestsエラーはrescueで拾い上げることが出来ます。

例:アカウントriocamposのフォロワーのアカウント名(:screen_name)を書き下す

注意:Twitter gemバージョン5の書き方をしています*1

#!/usr/bin/env ruby
# coding: utf-8
require 'twitter'

client = Twitter::REST::Client.new(KEY_SECRET_HASH)
begin
  followers = client.followers("riocampos").to_a
  followers.attrs[:users].each_with_index{ |tw, i|puts "#{i}: #{tw[:screen_name]}" }
rescue Twitter::Error::TooManyRequests => error
  sleep error.rate_limit.reset_in
  retry
end

Enumerable#to_aを使っているので、目的のユーザ(riocampos)のフォロワー数が一度に取得するフォロワー数(20アカウント)よりも多い場合には自動的に次を取得します(自動的に取得する仕組みについては別エントリに記載予定)。

余談:riocamposのフォロワー数は1月末時点で2000強です。つまり、APIで100回以上取得する必要があります。しかしAPIリミットは15回なので、少なくとも6回のAPIリミットに達しますorz APIリミットの枠は15分です。つまり、このスクリプトで全アカウント名を取得しようとすると1時間半かかりますorzorz やってられませんw 実は別のもっと良い方法がありますw Twitterフォロワーアカウント名の効率的な取得方法 - 別館 子子子子子子(ねこのここねこ)をご覧ください

errorオブジェクトの確認

さて、"Rate limit exceeded" errorが出たので、このerrorオブジェクトの中身を見てみます。
pryのlsを使って、インスタンスメソッドを確認します。

pry(main)> ls error
Exception#methods: 
  ==  backtrace  exception  inspect  message  set_backtrace  to_s
Twitter::Error#methods: cause  code  rate_limit  wrapped_exception
instance variables: @cause  @code  @rate_limit

後者のTwitter::Error#methodsが目的のものです。

  • error.cause / #wrapped_exception:エラー名です。"Rate limit exceeded"
  • error.code:エラーコードです。「88」詳細はこちらで→ https://dev.twitter.com/docs/error-codes-responses
  • error.rate_limit:Twitterサーバからのレスポンスがいろいろ入っています。
pry(main)> error.rate_limit
=> #<Twitter::RateLimit:0x007fd1f298b018
 @attrs=
  {"content-length"=>"81",
   "content-type"=>"application/json; charset=utf-8",
   "date"=>"Fri, 31 Jan 2014 06:04:21 UTC",
   "server"=>"tfe",
   "set-cookie"=>
    "guest_id=v1%3A139114826158013995; Domain=.twitter.com; Path=/; Expires=Sun, 31-Jan-2016 06:04:21 UTC",
   "strict-transport-security"=>"max-age=631138519",
   "x-rate-limit-limit"=>"15",
   "x-rate-limit-remaining"=>"0",
   "x-rate-limit-reset"=>"1391149151",
   "connection"=>"close"}>

attrsに入っているのでerror.rate_limit.attrs["x-rate-limit-remaining"]などというように呼び出しても良いのですが、もっと便利なメソッドが用意されています。

  • error.rate_limit.limit:エラーを出したAPIの上限回数です。
  • error.rate_limit.remaining:エラーを出したAPIの残存回数です。エラーが出ているので、必ず0ですw
  • error.rate_limit.reset_at:規制が解除される時刻です。
  • error.rate_limit.reset_in / retry_after:現在から規制が解除される時刻までの秒数です。900秒からのカウントダウンで最終的には0になります。

スクリプトで無駄なTwitterへのアクセスを避けるには

上記スクリプトで記載したように

  sleep error.rate_limit.reset_in

とすれば、規制中にTwitter APIアクセスすることを避けられます。

本当は規制される前に残存回数を知りたいですよね。その場合は前エントリを見てくださいw →Twitter APIリミットの残存回数取得メソッド - 別館 子子子子子子(ねこのここねこ)

*1:バージョン4以下の場合はclientオブジェクトのモジュールのRESTが不要となります。またclient.followers("riocampos").to_aの代わりにclient.followers("riocampos").allと表記してください。