2008-07-28
■ Twitter の API

前に Twitter が瀕死状態で、一時間あたりの API 回数制限が 30 になった頃、2,000 人も follow しているとログの取りこぼしばっかりだった。
ここ最近、自分の観測範囲 (約 2,400 人 follow している) では、24 時間の間で、2 万強のつぶやきが取れるのに、3 割程度のつぶやきを取りこぼしてて、14,000 強程度しか拾えない。
で、自分の中で Twitter 離れが起きて、DIS りはじめた頃、ある日いきなり一時間あたりの API 回数制限が 100 になった。
俗に言う KIH ((K) 急に (I) 一時間 (H) 100 回) である。
一応、ログ収集は cron で毎分動かしてて、実行時に rate_limit_status を見て頻度を調整していたんだけど、それだと 1 時間 60 回の壁を超えられないし、60 回だと発言が多い時間帯の取りこぼしが多く、一日あたりトータルで 1 割程度のつぶやきを取りこぼし、18,000 程度しか拾えてなかった。
ここ最近の制限は 1 時間に 100 回だから、つまり 36 秒おきに API を叩ける。
(ちなみに実際は follow とかを API 使って行なった場合、それも一回とカウントされてしまうから、自動 follow し返しとかやってる自分には、follow されすぎた時間帯は timeline 取得の API 実行回数が減る)
妙に頻発する取りこぼしが気持ち悪すぎるし、取りこぼした発言にすごく貴重な発言や、自分への発言が含まれてたりすると超嫌で、取りこぼしたくないと常々思っていたので、cron はやめて、プロセスを常駐させ、タイマーで動かすようにすれば取りこぼしが減ると思った。
で、実装してみて気付いた。
http://twitter.com/nipotan/statuses/869463516
hourly_limit が 100 だから 36 秒に一回 friends_timeline.json を GET してみたが、返ってくる JSON は 3 分ぐらいキャッシュされてる。つまり 180 秒ぐらい時間を置かずに頻繁に GET しても無意味。
何度も試して気付いたのは、friends_timeline.(xml|json) のレスポンスは、3 分間キャッシュされるという事実。
つまり、36 秒に一回とかいう頻度で timeline を取って来ても、180 秒に一回という頻度で timeline を取って来ても、結果は一緒。
実装を変えてから気付いたからショックが大きかった。
回避策として
http://twitter.com/nipotan/statuses/869464183
ちなみに XML と JSON でキャッシュが別々のようだから、交互に GET すれば 90 秒おきぐらいに新しい timeline が取得出来るかも知れない。
というアホな回避策にも気付いたが、結局取りこぼすであろうことにかわりはない。
そう言っていると id:cheebow さんが Twit でやってるという回避策として、URL にユニークな文字列をクエリにしてつけるとキャッシュされないかも知れないという情報を教えてくれた。
早速、リクエストに、friends_timeline.json?年月日時分秒μ秒 みたいな数字をくっつけてやってみた。
でもやはりキャッシュされてしまう。JSON だから?と思って XML にしてみたもののやっぱりキャッシュされている。
Twit が実際どうかと思ったので、ローカルの (キャッシュしない) proxy経由で Twit を使ってみたら、やはり同様に日時を末尾につけているんだが、3 分保持されているキャッシュを返されている模様。
だから、もしかしたら Twit でも 3 分に一回しか最新が流れてこないのかも知れない。
ここで API ドキュメントを見てて気付いたのは、since パラメータを渡すとどうなるかということが気になった。
で、実際に試してみた。
こっちで持っている最新の発言の日時を、HTTP Date の
Wed, 23 Jan 2008 04:56:07 GMT
こんなような形式で渡す。
HTTP の If-Modified-Since と同様な感じ。だから timezone は GMT 固定。
$datetime->set_time_zone('UTC'); $datetime->strftime('%a, %d %b %Y %H:%M:%S GMT');
みたいに。
クエリとして渡す時はちゃんとエスケープしてあげる
friends_timeline.json?since=Wed%2C+23+Jan+2008+04%3A56%3A07+GMT
そして、これで、指定した日時より後 (その日時は含まれない) の追加分のみ (最大 20 件) を取得することが出来る。
36 秒に一回だと、少ない時は、2、3 ぐらい。多い時で 12 ~ 15 ぐらいの発言が一度の API で拾える。
よく見たら、これで取りこぼしが皆無になった。
since パラメータがこんなに便利だったのに、全然知らなかったよ。
何か損した気分!