はてなブログをなんとなく開設してみました、私です。
エイプリルフールなネタというよりは、時間が経って考えてみたり実装してみたりしたらRtRTはTwitterのAPI仕様で十分いけるやんと気付いたので、こんな記事でも書いてみようかと思いました。
概要
公式RT直後の発言が分かる「RtRT」が面白い - ねとらぼ
http://nlab.itmedia.co.jp/nl/articles/1210/30/news118.html
こんな感じに
- 自分の発言がRTされる
- その後、RTした人がなにかそれについて言及しているかもしれない
- 気になるので拾ってみよう
という流れで、RTされた直後のつぶやきを取りに行くサービスを2012年10月からTwitter API1.0廃止まで運営してました。
この時点では
- 核になる3つのAPIの2つが廃止
- APIを叩ける回数が350回/1時間から15回/15分に変更
という2点の変更があり、今までどおりの運用は不可能と判断しサービスを停止するに至りました。
でも、最近になって、よく仕様を見てみるとなんだかできそう→できた、ということがあったので報告までしておきたいと思います。
あくまでRtRTは機能的に現在でも実装できる!というだけで、サービスは色々と面倒なので再開しません。
プログラムの流れ
- 自分がRTされたつぶやきの一覧を取得する(statuses/retweets_of_me)
- 各つぶやきをRTした人を調べる(statuses/retweets/)
- RTした人のTLを見にいって、自分のRT直後のつぶやきを見つける(statuses/user_timeline)
- データとして詰めあわせてjson形式で吐き出す
RTした人たちのユーザIDだけの取得でよければ、2はstatuses/retweeters/でも多分問題ありません。
API制限を見てみたらさらに実装可能感が増す
ここでAPI制限を確認してみますと、なんと各API毎に制限値と残数と復活までの時間が設定されたようで、現在では1と2は15回/15分、3は180回/15分となっているようです。
1はプログラム起動時に1回しか使う必要がなく、2はつぶやき毎に1消費しますが、15分に15個分を1度見られれば十分です。3はなぜか180回/15分も叩けるので以前の350回/1時間よりも効率が良くなっているという状態です。さらに、3のオプションであるcount=200とpage数に対応が取れるようになったため、つぶやき量が多い人に対してもかなり深くまでAPI回数を消費せずにリーチできるようになりました。
こういった点から、15分に一度の起動で100RT程度までの対応ならば問題なく行えるといえるでしょう。
Python2.7 + tweepyでコマンドラインからjson吐き出しまでを見てみます。
CONSUMER_KEY='XXXXXXXXXX'、CONSUMER_SECRET='XXXXXXXXXX'
ACCESS_KEY='XXXXXXXXXX'、ACCESS_SECRET='XXXXXXXXXX'
には、それぞれ自分のTwitter開発者用のものを入力してください。
import tweepy
import json
import codecs
LIMIT_RT = 5
LIMIT_PAGE = 20
LIMIT_COUNT = 100
CONSUMER_KEY='XXXXXXXXXXXXXXXXX'
CONSUMER_SECRET='XXXXXXXXXXXXXXXXX'
ACCESS_KEY='XXXXXXXXXXXXXXXXX'
ACCESS_SECRET='XXXXXXXXXXXXXXXXX'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth)
def getRtrt():
try:
retweets_of_me = api.retweets_of_me(count=LIMIT_RT)
except:
print 'auth or api error!(retweets_of_me)'
rtrt = []
for rt in retweets_of_me:
print rt.id
rtrts = []
try:
retweeter = api.retweets(id=rt.id_str)
except:
print 'auth or api error!(retweets)'
for rter in retweeter:
search_id = rter.id_str
print "whort:" + str(rter.user.screen_name)
rtrt_status = {}
b_flg = False
for p in range(1, LIMIT_PAGE):
if b_flg:
break
try:
tl = api.user_timeline(id=rter.user.id_str, count=LIMIT_COUNT, page=p)
except Exception:
print 'auth or api error!(user_timeline)'
print "p:"+str(p)+", c:"+str(len(tl))
for i, v in enumerate(tl):
if i == 0 or i == len(tl)-1:
print "id:"+v.id_str+":"+search_id
if v.id_str == search_id:
rtrt_status = {'user': {'id': tl[i-1].user.id_str,
'screen_name': tl[i-1].user.screen_name,
'protected': tl[i-1].user.protected,
'profile_image_url': tl[i-1].user.profile_image_url},
'id': tl[i-1].id_str,
'text': tl[i-1].text,
'created_at': str(tl[i-1].created_at)}
b_flg = True
break
elif v.id_str < search_id:
b_flg = True
break
if not rtrt_status:
rtrt_status = {'user': {'id': v.user.id_str,
'screen_name': v.user.screen_name,
'protected': v.user.protected,
'profile_image_url': v.user.profile_image_url},
'id': '',
'text': u'too much tweet!',
'created_at':''}
rtrts.append(rtrt_status)
rted_status = {'user': {'id': rt.user.id_str,
'screen_name': rt.user.screen_name,
'protected': rt.user.protected,
'profile_image_url': rt.user.profile_image_url},
'id': rt.id_str,
'text': rt.text,
'created_at': str(rt.created_at)}
rtrt.append({'rted_status':rted_status, 'rtrts':rtrts})
return rtrt
def wjson(content, filename):
f = codecs.open(filename + ".json", "w", 'utf-8')
json.dump(content, f, ensure_ascii=False, indent=4)
f.close
get_rtrt()した中身をwrite_json()に入れてjson形式で出力します。
[
(中略)
{
"rted_status": {
"text": "話がジェットコースターなので、よくよく考えるとなんかおかしいところもある気はするけど、作品全体でのパゥワが凄すぎる。",
"created_at": "2014-03-22 14:32:38",
"user": {
"protected": false,
"id": "14382115",
"profile_image_url": "http://pbs.twimg.com/profile_images/378800000394120263/9fe4afc9596c0f7163fce33261bce6c2_normal.png",
"screen_name": "esuji"
},
"id": "447380337069277184"
},
"rtrts": [
{
"text": "私の好きな作品によくある事( ´ω` )",
"created_at": "2014-03-22 14:35:22",
"user": {
"protected": false,
"id": "XXXXXXXXXXXXXXX",
"profile_image_url": "http://pbs.twimg.com/profile_images/XXXXXXXXXXX",
"screen_name": "XXXXXXXXXXX"
},
"id": "XXXXXXXXXXXXXXXXXXXX"
}
]
},
(中略)
]
あまりRT言及っぽいのが取れなかったですが、上が私のつぶやきで下がその直後のつぶやきです。許可をもらってないので個人情報をマスクしておきましたが、実際にはちゃんと取れています。
あとはこのjsonをjavascriptなんかで整形してやれば、きちんとコンテンツになります。
ただ、そのためにサーバやらなんやらの用意をする気力が私にはないので、やる気のある方が出てくれればというところです。
ということで、RtRTがダメになったというのは事実と異なる見解でした、すみません。
というところで本題は締めたいと思います。
実装についてもうちょっと詳しく
①兎にも角にもまずはアプリ用のトークンが必要です。
(上記で自分で入力する必要がある4つの文字列)
こちらはPHPの記事ですが、トークンをゲットするまでは同じ道のりなので参考になると思います。
http://webnaut.jp/develop/633.html
②Pythonとtweepyをインストールする。
特に説明するほどでもない気がするので、ぐぐっていただけると話が早いです。
私はPython2.7を使用しましたが、3系でもそこまで問題ないような気がします。
③上記のソースコードに自分のCONSUMER_KEY、CONSUMER_SECRET、
ACCESS_KEY、ACCESS_SECRETを入力して任意の名前(ここでは例としてrtrt.py)で保存。
コマンドプロンプトやらコンソールやらでPythonの対話モードシェルを起動。
>>> import rtrt
>>> json = rtrt.get_rtrt()
>>> rtrt.json_write(json, 'rtrt')
これで同じフォルダにrtrt.jsonが生成される。
これをテキストエディタで開いて眺めたり、javascriptで整形して表示したりすると幸せになれる(※個人差があります)
謝辞として、各APIの仕様と取ってくるデータを確認するのにtwitSandbox様には大変お世話になりました。
http://twitsandbox.com/
また、参考にさせていただいたサイト、ブログ様もたくさんありますが、ありすぎて一つ一つは覚えてません、すみません・・・。