やる夫と Python で学ぶ Twitter の OAuth
OAuth 調べてみたら難しくて理解出来なかったので,
Python で標準ライブラリだけで 1 から書いてみました.
/ \ / _ノ ヽ、_ \ / o゚((●)) ((●))゚o \ twitter の OAuth 難しいお… | (__人__)' | \ `⌒´ / ____ /⌒ ⌒\ /( ●) (●)\ /::::::⌒(__人__)⌒::::: \ だからやる夫でやるお! | |r┬-| | \ `ー'´ /
Python のサンプルコードを付けていますが,
上から順に読めるようにおもいっきり手続き型で書いています.
コメントで実際の処理の説明を書いています.
Consumer Key と Consumer Secret の入手
/ ̄ ̄\ / u \ .____ |:::::: u | ./ \ OAuth 出来るようにしたいので . |::::::::::: | / ⌒ ⌒ \ アクセストークンください |:::::::::::u: |/ (●) (●) \ . |:::::::::::::: u } | (__人__) | . ヽ:::::::::::::: } \ ` ⌒´ _/ ヽ:::::::::: ノ | \ /:::::::::::: く | | | | -―――――|:::::::::::::::: \-―┴┴―――――┴┴―― |:::::::::::::::|ヽ、二⌒) それじゃあ,この画面で登録してくださいね ____ / \ /\ キリッ . / (ー) (ー)\ こんなの簡単だお / ⌒(__人__)⌒ \ | |r┬-| | \ `ー'´ / ノ \ /´ ヽ | l \ ヽ -一''''''"~~``'ー--、 -一'''''''ー-、. ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒)) ___ ━┓ / ― \ ┏┛ / (●) \ヽ ・ / (⌒ (●) / あれ?? ここに登録しても Consumer Key と Consumer Secret しか /  ̄ヽ__) / 手にはいらないお? . /´ ___/ | \ | |
というわけで,
http://dev.twitter.com/apps/new
にアクセスして登録すると Consumer Key と Consumer Secret が手に入ります.
リクエストトークンの取得
/ ̄ ̄\ / u \ .____ |:::::: u | ./ \ Consumer Key と Consumer Secret を手に入れたので . |::::::::::: | / ⌒ ⌒ \ アクセストークンください |:::::::::::u: |/ (●) (●) \ . |:::::::::::::: u } | (__人__) | . ヽ:::::::::::::: } \ ` ⌒´ _/ ヽ:::::::::: ノ | \ /:::::::::::: く | | | | -―――――|:::::::::::::::: \-―┴┴―――――┴┴―― |:::::::::::::::|ヽ、二⌒) それは,別の窓口(URL)で申請して下さい / ̄ ̄ ̄\ / ─ ─ \ 日本の役所かお!? / (○) (○) \ | (__人__) | \ ` ⌒´. / / \ / ̄ ̄ ̄ \ ホジホジ / ― ― \ / (●) (●) \ アクセストークン下さい | (__人__) | \ mj |⌒´ / 〈__ノ ノ ノ / ̄ ̄\ / _ノ \ | ( ●)(●) アクセストークンの取得にはリクエストトークンが必要ですので . | (__人__) こちらの形式で認証してください | ` ⌒´ノ . | } . ヽ } ヽ ノ \ / く \ \ | \ \ \ | |ヽ、二⌒)、 \ ___ / \ /ノ \ u. \ (ちょ、なんだか面倒臭くなってきてるお) / (●) (●) \ | (__人__) u. | \ u.` ⌒´ / ノ \ /´ ヽ
というわけで,リクエストトークンの取得です.
Python で書いてみます
#!/usr/bin/env python # -*- coding: utf-8 -*- import time, random, urllib, cgi, hmac, hashlib consumer_key = 'さっきの画面に出てきたやつ' consumer_secret = 'さっきの画面に出てきたやつ' # Request Token は GET で取得 method = 'GET' # Request Token 取得の URL request_token_url = 'http://twitter.com/oauth/request_token' # 必須パラメータを準備 params = { "oauth_consumer_key": consumer_key, # WEB で登録した oauth consumer key "oauth_signature_method": "HMAC-SHA1", # 暗号のアルゴリズム "oauth_timestamp": str(int(time.time())), # unixtime "oauth_nonce": str(random.getrandbits(64)), # ランダム文字列 "oauth_version": "1.0" # バージョン番号 } # パラメータをソートし,URIエンコードした key=value の形にして & で繋げます params_str = '&'.join(['%s=%s' % (urllib.quote(key, ''),urllib.quote(params[key], '')) for key in sorted(params)]) # メソッド,URIエンコードした URL,上で作ったパラメータ文字列を & で繋げます message = '%s&%s&%s' % (method,urllib.quote(request_token_url,''), urllib.quote(params_str,'')) # consumer_secret を元にキーを作成します key = "%s&%s" % (consumer_secret, '') # キーを元に message で hmac を作成します signature = hmac.new(key, message, hashlib.sha1) # そのダイジェストを base64 でエンコードし,余計な空白を取り除きます digest_base64 = signature.digest().encode("base64").strip() # 作成したダイジェストをパラメータに追加します params['oauth_signature'] = digest_base64 # 作成したパラメータを GET のパラメータとして追加します _url = request_token_url+ '?' + urllib.urlencode(params) # その URL にアクセスし, ResponseBody を読み込みます result = urllib.urlopen(_url).read() # パースします data = cgi.parse_qs(result) # 取得できました!! print data #{'oauth_token_secret': ['xxx'], 'oauth_token': ['xxxx'], 'oauth_callback_confirmed': ['true']} # oauth_token がリクエストトークン
注意点としては,ここで取得出来た oauth_token,oauth_token_secret は一時的なものだという事です.
この後に出てくるアクセストークンの取得を行なった後は無効になりますので注意してください.
OAuth Verifier の取得
/ ̄ ̄\ / u \ .____ |:::::: u | ./ \ OAuth Token と OAuth Token Secret を手に入れたので . |::::::::::: | / ⌒ ⌒ \ アクセストークンください |:::::::::::u: |/ (●) (●) \ . |:::::::::::::: u } | (__人__) | . ヽ:::::::::::::: } \ ` ⌒´ _/ ヽ:::::::::: ノ | \ /:::::::::::: く | | | | -―――――|:::::::::::::::: \-―┴┴―――――┴┴―― |:::::::::::::::|ヽ、二⌒) こちらはリクエストトークンの窓口(URL)ですので,それは別の窓口(URL)で申請して下さい / ̄ ̄ ̄\ / ─ ─ \ またかお!? / (○) (○) \ | (__人__) | \ ` ⌒´. / / \ / ̄ ̄ ̄ \ ホジホジ / ― ― \ / (●) (●) \ アクセストークン下さい | (__人__) | \ mj |⌒´ / 〈__ノ ノ ノ / ̄ ̄\ / _ノ \ | ( ●)(●) アクセストークンの取得にはユーザに認証してもらって . | (__人__) OAuth Verifier を取得してもらう必要があります | ` ⌒´ノ . | } . ヽ } ヽ ノ \ / く \ \ | \ \ \ | |ヽ、二⌒)、 \ ___ / \ /ノ \ u. \ (ちょ、まだ貰えないのかお) / (●) (●) \ | (__人__) u. | \ u.` ⌒´ / ノ \ /´ ヽ
というわけで,OAuth Verifier の取得ですが,今回はクライアントとして使いたいので,
単純に先程取得した oauth_token をパラメータに付けてアクセスするだけです.
# さっき取得したデータから oauth_token を取得してひっつける print 'http://twitter.com/oauth/authorize?oauth_token='+data['oauth_token'][0]
これで表示されたアドレスにブラウザでアクセスし,アプリケーションからの使用を許可すると
画面に OAuth Verifier が表示されます.
アクセストークンの取得
べ,別の窓口(URL)になります… |/ γ ⌒⌒ヽ / ̄ ̄\ ( ( ヽ ) ノ /_ノ \ (⌒) 三 ノ 从 ゝ ( ●)( ●) ヽ 三/ | ニ ____ (⌒) . | (__人__) u } | | /\ / ) し / | ミ | ` ⌒´ ノ ! 、 /(○ )::(○ )⌒\/ | ミ . | } \./:::::::(_人_):::::::: i' | OAuth Verifier 手に入れたから . ヽ } | )ww) | | いい加減アクセストークン教えてくれお! ヽ ノ ヘ \ `ー" ノ / く 、_/っ/ \ . . \ | \--一'' \ | |ヽ、二⌒)、 \ ____ /ノ ヽ、_\ 一体どういうことだお!!!! /( ○)}liil{(○)\ どんだけ手続踏ませるんだお!!!! / (__人__) \ アクセストークン手に入れるだけで | ヽ |!!il|!|!l| / | 日本の役所以上にたらいまわしじゃないかお!! \ |ェェェェ| / / ̄ ̄ ̄ \ ホジホジ / ― ― \ / (●) (●) \ って怒ってもしょうがないのは役所で慣れてるお | (__人__) | \ mj |⌒´ / 〈__ノ ノ ノ |┃ ガラッ. |┃ |┃ ノ// ./ ̄ ̄ ̄ \ |┃三 / \ / \ OAuth Verifier 手に入れたから |┃ / (●) (●) \ アクセストークンくれお |┃ | (__人__) | |┃三 \ ` ⌒´ / |┃三 / ̄ ̄ ̄ ̄ ̄ ̄ ̄ \ / ̄ ̄\ |┃┃ / _ノ \ 三 .|┃┃ | ( ●)(●) ..|┃┃ . | (__人__) . |┃┃ | ` ⌒´ノ |┃┃ . | } 三 |┃┃ . ヽ } |┃┃ピシャッ! ヽ ノ三 ..|┃┃ / く \ .|┃┃ | \ 三 |┃┃ | |ヽ、二⌒) |┃┃ |┃ ガラッ ____ |┃ 三 /u \ |┃ / \, 、/ \ |┃ . / ( ●) (● ) \ |┃ 三 | '" (__人__)"' u | < 閉めないでくれおっ! |┃ \ ` ⌒ ´ / |┃ /ゝ "` ィ `ヽ. |┃ 三 / \ ,⊆ニ´⌒ ̄ ̄" y r、 ヽ ⊂二、 ,ノ──-‐'´| | l" | |┠ ' | l/'⌒ヾ |┃三 | |ヾ___ソ ___ / \ / ::\:::/::::u.\ ./ ̄ ̄\ / <●>::::::<●> \ / .ヽ | (__人__)u. | .| :::::::l \ u.` ⌒´ / | ::::::::::l /⌒ヽ ー‐ ィヽ | :::::::::::::l / ■ ■ .冊 冊. { u :::::::::::::::::l ではこちらへアクセスしてください… /, ./ ∨ ヽ (.サ.)(.サ.) { ::::::::::::::::/ | .l六-0l六-0l } ソ { } ソ {ヽ ゝ ::::::::::::/ ゝ つ=.l==l(.ポ.).(と⌒.ノ > :::::::::ヽ  ̄ ̄ ゙ヽ_ソノノ--ィ ゝ-ヘゝゝノ゙  ̄/ :::::::::::::::::i ̄ ____ /⌒ ⌒\ /( ●) (●)\ /::::::⌒(__人__)⌒:::::\ (お!! やっとアクセストークン貰えそうだお!!!) | |r┬-| | \ `ー'´ /
と,いうわけでやっとアクセストークンの取得です.
#!/usr/bin/env python # -*- coding: utf-8 -*- import time, random, urllib, urllib2, cgi, hmac, hashlib consumer_key = '最初に使ったやつ' consumer_secret = '最初に使ったやつ' oauth_token = 'リクエストトークン取得の時に取得した OAuth Token' oauth_token_secret = 'リクエストトークン取得の時に取得した OAuth Token Secret' oauth_verifier = 'ブラウザに表示された OAuth Verifier' # Access Token は GET で取得 method = 'GET' # Access Token 取得の URL access_token_url = 'http://twitter.com/oauth/access_token' # 必須パラメータを準備 params = { "oauth_consumer_key": consumer_key, # WEB で登録した oauth consumer key "oauth_signature_method": "HMAC-SHA1", # 暗号のアルゴリズム "oauth_timestamp": str(int(time.time())), # unixtime "oauth_nonce": str(random.getrandbits(64)), # ランダム文字列 "oauth_version": "1.0" # バージョン番号 } # パラメータに先程取得した値を追加 params['oauth_token'] = oauth_token params['oauth_verifier'] = oauth_verifier # パラメータをソートし,URIエンコードした key=value の形にして & で繋げます params_str = '&'.join(['%s=%s' % (urllib.quote(key, ''),urllib.quote(params[key], '')) for key in sorted(params)]) # メソッド,URIエンコードした URL,上で作ったパラメータ文字列を & で繋げます message = '%s&%s&%s' % (method,urllib.quote(access_token_url,''), urllib.quote(params_str,'')) # consumer_secret と oauth_token_secret を元にキーを作成します key = "%s&%s" % (consumer_secret, oauth_token_secret) # キーを元に message で hmac を作成します signature = hmac.new(key, message, hashlib.sha1) # そのダイジェストを base64 でエンコードし,余計な空白を取り除きます digest_base64 = signature.digest().encode("base64").strip() # 作成したダイジェストをパラメータに追加します params['oauth_signature'] = digest_base64 # ヘッダに Authorization:OAuth を追加します opener = urllib2.build_opener() opener.addheaders = [('Authorization','OAuth')] # 作成したパラメータを GET のパラメータとして追加します _url = access_token_url + '?' + urllib.urlencode(params) # その URL にアクセスし, ResponseBody を読み込みます result = opener.open(_url).read() # パースします data = cgi.parse_qs(result) # 取得できました!! print data #{'oauth_token_secret': ['xxxx'], 'user_id': ['xxxx'], 'oauth_token': ['xxxx'], 'screen_name': ['yaruo']} # oauth_token がアクセストークン
成功すると,アクセストークンの他にもユーザ名などもわかります.
リクエストトークンのところでも説明しましたが,
ここで出た oauth_token と oauth_token_secret を保存しわすれると,
もう一度リクエストトークンの取得からになるので注意してください.
つまり,このプログラムを連続で実行すると 2 度目以降はエラーになります.
アクセストークンを使って実際に Twitter にアクセスしてみる
____ /⌒ ⌒\ いっぱい苦労したけど /( ●) (●)\ アクセストークン手に入れたお!! /::::::⌒(__人__)⌒:::::\ 苦労が報われるお!! | |r┬-| | \ `ー'´ / ____ /⌒ ⌒\ /( >) (<)\ さっそくアクセストークン使って /::::::⌒(__人__)⌒:::::\ Twitter に「おっぱい」って書き込むお!! | /| | | | | | \ (、`ー―'´, /
では,実際にアクセスしてみましょう.
今回は twitter に発言をするサンプルです.
#!/usr/bin/env python # -*- coding: utf-8 -*- import time, random, urllib, urllib2, cgi, hmac, hashlib, commands # 発言内容 text = u'おっぱい' consumer_key = '最初に使ったやつ' consumer_secret = '最初に使ったやつ' oauth_token = 'アクセストークン取得の時に取得した OAuth Token' oauth_token_secret = 'アクセストークン取得の時に取得した OAuth Token Secret' # 発言の URL update_url = 'http://twitter.com/statuses/update.json' # 必須パラメータを準備 params = { "oauth_consumer_key": consumer_key, # WEB で登録した oauth consumer key "oauth_signature_method": "HMAC-SHA1", # 暗号のアルゴリズム "oauth_timestamp": str(int(time.time())), # unixtime "oauth_nonce": str(random.getrandbits(64)), # ランダム文字列 "oauth_version": "1.0" # バージョン番号 } # パラメータに必要な値を追加 params['oauth_token'] = oauth_token params['status'] = text # パラメータの値が unicode だったらエンコードします for k,v in params.items(): if isinstance(v, unicode): params[k] = v.encode('utf8') # パラメータをソートし,URIエンコードした key=value の形にして & で繋げます params_str = '&'.join(['%s=%s' % (urllib.quote(key, ''),urllib.quote(params[key], '~')) for key in sorted(params)]) # メソッド,URIエンコードした URL,上で作ったパラメータ文字列を & で繋げます message = '%s&%s&%s' % ('POST',urllib.quote(update_url,''), urllib.quote(params_str,'')) # consumer_secret と oauth_token_secret を元にキーを作成します key = "%s&%s" % (consumer_secret, oauth_token_secret) # キーを元に message で hmac を作成します signature = hmac.new(key, message, hashlib.sha1) # そのダイジェストを base64 でエンコードし,余計な空白を取り除きます digest_base64 = signature.digest().encode("base64").strip() # 作成したダイジェストをパラメータに追加します params['oauth_signature'] = digest_base64 # ヘッダには API に必要なパラメータは含めないので消します del params['status'] # パラメータをソートし,URIエンコードした key=value の形にして , で繋げます header_params_str = ",".join(["%s=%s" % (urllib.quote(k,''), urllib.quote(params[k],'~')) for k in sorted(params)]) print header_params_str # ヘッダに Authorization:OAuth + 上で作成した文字列を追加します opener = urllib2.build_opener() opener.addheaders = [('Authorization','OAuth %s' % header_params_str)] # あとは普通に API を呼び出します result = opener.open(update_url,urllib.urlencode( {'status':text.encode('utf-8')})).read()
おっぱい
._ \ヽ, ,、 `''|/ノ .| _ | \`ヽ、| \, V `L,,_ |ヽ、) ,、 / ヽYノ / r''ヽ、.| | `ー-ヽ|ヮ | `| |. | ヽ、 | ヽ____ノ /_ノ ' ヽ_\ /(≡) (≡)\ /::::::⌒(__人__)⌒::::: \ | |r┬-| | \ `ー'´ / / \ ( | | ) \| э |/ ( ,,,, ,ノ \ 、(U)ノ ノ \/ / ┼ヽ -|r‐、. レ | / /\ d⌒) ./| _ノ __ノ ⊂⌒__)__)
結論 : めんどくさすぎるので,ライブラリ使いましょう