TwitterのApplication-only authenticationを試してみた
Application-only authentication
今さらだけどTwitterのAPIバージョンが1.1になってユーザー認証しないとAPI叩けないのかなとか思ってたら、ちょっと前に新しい認証方式が出てたみたいなので試してみたというお話。
タイトルにもあるようにApplication-only authenticationっていう方式でOAuth2.0にもとづいたものらしい。従来のOAuth1.0を使った認証と比べるとだいぶ簡単で、API回数制限も検索なんかはユーザーごとのものよりもかなり緩和されてる。その代わりにユーザー認証が必要なユーザーのタイムラインとかDMみたいなAPIが使えないっていう制限はある。
立ち位置的にはこれまでOAuthなしで使えてたAPIの置き換えみたいなものかと。
もうちょっとちゃんとしたまとめ
Perlで実装
このPerlでの実装を参考にしてこのページの訳的な感じで認証方法を簡単にまとめてみた。具体的な手順は以下。
まずはここでアプリケーションの登録をしてコンシューマーキーとシークレットをもらってくる。で、この2つをURIエンコードした文字列を":"でつないだものをBase64エンコードしてあげる。
Pythonで書くとこんな感じ。
token_credential = urllib.quote(oauth_consumer_key) + ':' + urllib.quote(oauth_consumer_secret)
credential = base64.b64encode(token_credential)
アクセストークン取得
次にこの文字列を使ってアクセストークンを取得してくる。リクエストのAuthorizationヘッダに"Basic " + さっきの文字列を突っ込んで、Content-Typeに"application/x-www-form-urlencoded;charset=UTF-8"を入れる。リクエストボディには"grant-type=client_credentials"を入れておく。
で、https://api.twitter.com/oauth2/tokenにPOSTでリクエストを送るとアクセストークンの入ったJSONが返ってくる。通常のOAuthと比べると特別なライブラリもなしでアクセストークンを取得できるのがわかるかと。
url = 'https://api.twitter.com/oauth2/token' value = {'grant_type': 'client_credentials'} data = urllib.urlencode(value) req = urllib2.Request(url) req.add_header('Authorization', 'Basic ' + credential) req.add_header('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8') response = urllib2.urlopen(req, data) json_response = json.loads(response.read()) access_token = json_response['access_token']
署名付きリクエスト
後はこのアクセストークンを使って、リクエストのAuthorizationヘッダに"Bearer " + アクセストークンを付けてAPIアクセスをするだけ。なんて簡単(´∀`)
とりあえず検索APIを叩いてみる。
url = 'https://api.twitter.com/1.1/search/tweets.json' query = {'q': 'japan'} req = urllib2.Request(url+'?'+urllib.urlencode(query)) req.add_header('Authorization', 'Bearer ' + access_token) response = urllib2.urlopen(req) json_response = json.loads(response.read()) json_str = json.dumps(json_response)
最後にまとめ。
とりあえず検索APIの回数制限が450回らしいので451回アクセスしてみるスクリプト。
ちょうどヨルダン戦やってるのでjapanを検索してみたり。
大量に結果が吐き出されます。
回数制限を超えるとこんな感じでエラーが返ってくる。
$python test_app_only_auth.py ... {"errors":[{"message":"Rate limit exceeded","code":88}]} 450
検索とかタイムラインからのデータ取得とかするならこれからはこれ使うことになるかと。
せっかくなんでこれ使ってなんかやってみようかな。