« Androidって美味しい? | screenとは?【初心者入門編】 »

2010.08.24

Google App EngineでTwitterを活用する

このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをnewsingに追加

今回は、Google App Engine (GAE) でTwitter上のデータを集約するRSSリーダーのようなアプリを作りたいと思います。

解説する内容は以下になります。

  1. Google App Engine (GAE) の利用方法
  2. Twitter API の利用方法
  3. ツイートの集積と簡単な未読・既読処理

 

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

No comments.

Comment feed

Comment





XHTML: You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>