2010.08.24
Google App EngineでTwitterを活用する
今回は、Google App Engine (GAE) でTwitter上のデータを集約するRSSリーダーのようなアプリを作りたいと思います。
解説する内容は以下になります。
- Google App Engine (GAE) の利用方法
- Twitter API の利用方法
- ツイートの集積と簡単な未読・既読処理
1. Google App Engine (GAE) の利用方法
GAEの利用
GAEはGoogleが提供するクラウドインフラです。 制約はありますが、ウェブサービスを作ることができます。URL フェッチやクーロンタスク も可能です。
なんといっても、無料で始めることができます。規模の原理が効いているので、通常のサーバーよりもコストが低くなります。
GAEを始めるには、http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/devenvironment.htmlのチュートリアルを一通りこなすのがよいでしょう。
web2pyの利用
GAEをより手軽に利用するために,ここではweb2pyフレームワークを利用します。
web2pyの特徴はGAE上”でも”動くことです。GAEのバックエンドは特殊な分散ストレージになっており、通常のデータベースとは異なります。JOIN句や、特異性の低い条件式、集計関数も利用できず、ソートや範囲選択にも制限があります。これらの制約を守る必要がありますが、web2pyを利用すると、同じコードで通常のサーバーと同時に、GAE上でも動かすことができます。
wab2pyはもともと大学での教育用として開発されていることもあり、習得が容易です。http://www.scribd.com/doc/12288297/Web2py-vs-Othersや、http://web2py.com/examples/default/examplesにある例題をみれば、簡潔に記述できるのが分かるかと思います。
セットアップは、http://www.web2py.com/examples/default/downloadから、ソースコードをダウンロードするだけです。
開発サーバーの起動は、ソースディレクトリに行き,”python web2py.py -a password” とコマンドを打ちます。 http://127.0.0.1:8000を開くと、最初はデモアプリケーションが表示されます。/admin/default/indexにアクセスすると管理画面が表示されます(管理画面はローカルホストからか、SSLを通してのみしか閲覧できません)。
自分のアプリケーションを作るには、”python web2py.py -S myapp”とコマンドを打ちます。/myapp/default/indexにアクセスすると、最初はデモアプリケーションと同様の画面が表示されます。
GAEへのデプロイ
まずは、GAEの開発サーバー上で、web2pyのアプリケーションを動かしてみましょう。GAEのSDKのディレクトリに行き、”python dev_appserver.py /path/to/web2py”とコマンドを打ちます。ここで、一通り、動作確認を行ないます。このとき、利用したデータベース・クエリの中で、GAE上で必要なインデックスの定義は、index.yamlファイルに自動的に書き込まれます。
web2pyのソースディレクトリのトップには、app.yamlというファイルがあります。ここに、https://appengine.google.com/で登録したアプリケーションのIDを設定します。また、余計なファイルやディレクトリがある場合は、このファイルにて、あらかじめ指定しておきます。
最後に、”python appcfg.py update /path/to/web2py”とコマンドを打って、web2pyのソースコードをGAEにアップします。
http://myappid.appspot.com/myapp/…にアクセスすると、開発サーバーと同様の画面が表示されます。なお、本番サーバでのエラーは、ダッシュボードのログ(https://appengine.google.com/logs?&app_id=myappid)に記録されます。
2. Twitter APIの利用方法
Twitter APIの利用制限
Twitter APIには、匿名リクエストがIP 毎に1時間に150 回までという制約があります。GAE上でTwitter APIを叩くことはできますが、GAEではIP を共有利用しているので、すぐにその制約にひっかかてしまいます。
そこで、OAuth認証というものを利用します。これにより、IP制約がなくなります。また、利用数は1 時間に350回までになり、Twitterにログインした状態と同じことができるようになります。
OAuth認証の設定
1.Twitterにてアプリケーションの登録
OAuth認証を利用可能にするために、APIを利用するアプリケーションの登録をまず行ないます。登録は、https://twitter.com/appsから行ないます(参考)。幾つかの設定項目がありますが、基本的には、適当なアプリ名を登録するだけです (なお、ここでは説明のため,Application Typeは、”認証後、指定URLにリダイレクトしない”Clientに設定しておきます)。
登録後、Cunsumer Token (”consumer key”と”consumer secret”というパスワード文字列)が取得できるので、これをメモってください。
2.Access Tokenの取得
OAuth認証でAPIを叩くときは、ユーザー・アカウント毎に”Access Token”という鍵が必要です。
自分のアカウントだけを利用する場合は、http://dev.twitter.com/apps/から自分のアプリケーションを選択し、”My Access Token”というリンクを開くと、Access Tokenを取得することができます。
それ以外の場合は、少し複雑な手順を踏みます。ここでは、Twitter APIのPython ラッパーであるtweepyを利用して説明します。
手順1 Consumer Token から auth オブジェクトを作成 :
import tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret )
手順2 Redirect URL と Request Token を取得 :
redirect_url = auth.get_authorization_url()
request_key = auth.request_token.key
request_secret = auth.request_token.secret
→ これらの出力をメモ
手順3 取得した Redirect URL を (twitter にログインした状態で)開く :
→ アクセス権を承認する
→ 7 桁の数字が表示されるので、 これもメモ
(Twitterのアプリケーションの設定で”Application Type”をBrowserにすると、
承認後、Callbak URL にリダイレクトされる)
手順4 Access Token の取得 :
auth.set_request_token(request_key, request_secret )
auth.get_access_token(verifier_digits ) # verifier_digitsは取得した7桁の数字
access_key = auth.access_token.key
access_secret = auth.access_token.secret
→ これらの出力をメモ
3.APIの利用
取得したConsumer Tokenと、Access Tokenを用いてTwitter APIを利用します。ここでは、tweepyライブラリを利用します。
import tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret )
auth.set_access_token(access_key, access_secret ) # これで API が利用可能に
api = tweepy.API(auth)
# 公開タイムラインを取得してみる
public_tweets = api.public_timeline()
for tweet in public_tweets:
print(tweet.text)
3.ツイートの集積と 簡単な未読・既読処理
tweepyライブラリのweb2pyへのインポート
tweepyライブラリのソースディレクトリをweb2pyのソースディレクトリにあるsite-packages以下に保存します。jsonモジュールへのパスが通ってない場合、tweepyライブラリのtweepy/utils.pyにあるimport_simplejsonの関数を編集し、gluon.contrib.simplejsonをインポートするようにしてください。
ツイートモデルの定義
applications/myapp/models/db.pyを以下のように編集し、簡単なツイートモデルを定義します。ちょっとした応用として、未読既読の設定ができるようにもしてみます。
…
db.define_table(
’tweet’, #データベースのテーブル(GAEではKind)名
Field(’uuid’, ‘integer’), #ツイートID
Field(’tweeted_at’, ‘datetime’), #ツイート時刻
Field(’content’, ’string’), #ツイート本文
Field(’user_name’, ’string’), #ユーザーの名前
Field(’user_image’, ’string’), #ユーザーの画像
Field(’read_flg’, ‘boolean’, default=False), #未読・既読の設定
))
ツイートの集積
あるツイートID以降の上限何件まで取得するAPIを用い、そのAPIを一定間隔で叩きます。
最後に取得したツイートIDを記録しておけば、重複して取得することを防ぐことができます。
一連の処理は、applications/myapp/controllers/default.pyの中で、aggregate_tweets()という関数を定義し、ロジックを書き込んでいきます。
まず、APIを叩いてツイートを取得するコードは以下のようになります。
tweets = api.home_timeline(since_id, count=COUNT)
次に、最後に取得したツイートID(since_id)の取得&保存は、ここではキャッシュを利用して行ってみます。web2pyの開発環境の場合はメモリが、GAEの場合はmemcacheがキャッシュのバックエンドになります。現時点では仕様が異なる部分があるので、少し条件分岐を行います。
# 最後に取得したツイートIDの取得
if request.env.web2py_runtime_gae: # GAEの場合
since_id = cache.ram.get(’home_since_id’)
else: # 開発環境の場合
since_id = cache.ram(’home_since_id’, lambda: ‘0′, EXPIRE)
since_id = long(since_id) if since_id else None
# ツイートの取得
tweets = api.home_timeline(since_id, count=COUNT)
# 最後に取得したツイートIDの保存
new_since_id = str(tweets[0].id) if tweets else str(since_id)
if request.env.web2py_runtime_gae: # GAEの場合
cache.ram.set(’home_since_id’, new_since_id, EXPIRE)
else: # 開発環境の場合
cache.ram.clear(’home_since_id’)
cache.ram(’home_since_id’, lambda: new_since_id, EXPIRE)
続いて、データベースへの保存は以下のように行ないます。
for tweet in tweets:
db.tweet.insert(
uuid=tweet.id,
user_name=tweet.user.screen_name,
user_name=tweet.user.profile_image_url,
content=tweet.text,
tweeted_at=tweet.created_at,
)
上記のコードを書いたら、myapp/default/aggregate_tweetsのアドレスを叩いてみてください。
aggregate_tweets関数が実行されます。管理画面からデータベースを見てみると、ツイートが保存されているはずです。
APIを一定間隔で叩くには、GAEの場合,Cronサービスを利用します。その他の場合は,web2pyのcron機能も利用することができます。
ツイートの表示
今度は、applications/myapp/controllers/default.pyの中で、read_tweets()という関数を定義し、未読のツイートを表示させてみます。表示後は、既読に設定することも行ってみます。
# 未読ツイートの取得(上限0~20、ツイート時刻の降順で)
tweets = db(db.tweet.read_flg==False
).select(limitby=(0, 20), orderby=~db.tweet.tweeted_at)
#未読を既読に設定
for tweet in tweets:
tweet.update_record(read_flg=True)
#ビューのテンプレートにコンテキストを渡す
return dict(tweets=tweets)
ここで、未読ツイートの取得の際に、read_flgによる絞り込みと、tweeted_atによるソートを行なっている点に注意してください。通常のデータベースではこのようなクエリはすぐに実行できますが、GAE上では特定のインデックスを貼らないといけません。GAEの開発サーバーで、一旦、このクエリを実行しておき、設定ファイルに必要なインデックスを書き込ませておきましょう。
出来上がったら、myapp/default/read_tweetsを開いてみてください。未読ツイートが上限20件で表示されます。
GAE+Twitterの可能性
以上で簡単なツイートリーダーの説明は終わりです。
けっこう、手軽?に作ることができたのではないでしょうか。
もっと発展させれば、次のような実装も可能になると考えられます。
- ユーザー毎に未読数・既読数の表示
- メンションやリツイートなどに関する詳細分析
- 頻出単語の算出
- 個人の嗜好を反映したツイートの分類
GAE+Twitterには、新しい可能性がありそうです。
ぜひ、何かチャレンジしてみてはいかがでしょうか?
Trackback URL
Comment & Trackback
Comment feed
Comment