Google App Engineを使ったTwitterBotの作り方

 のっちフライデーのショックで一気に書き上げました(嘘)。Google App Engine(以下GAEと略)を用いて℃-uteのなっきぃをTwitterに召喚しました。なかさきBotです。
http://twitter.com/_nksk
今回はなかさきBotをどう作ったのかまとめて、チュートリアル的なものを書いてみました。かなり適当に作ってるので、ここ違うよ!とか、こう書けばいいんじゃない?みたいなコメント大歓迎です。GAEの入門編は以下のリンクを読んでください。ほとんどそこと同じことを書いてます。
http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/
開発環境はWindows XPで、言語はPythonで書いてます。初Pythonでしたけど難しくなかったですよ。準備として、まずPythonのダウンロード。最新版はダメです。2.5.xをダウンロード、インストールしてください。次にGoogle App Engine SDKのダウンロードとインストール。こちらは最新版でOKです。ここでは便宜的にnkskbotというアプリケーションを作ることにします。アプリケーション名がnkskbotです。まず、どこでもいいのでアプリケーション用のディレクトリを作ります。GAEでは、そこにアプリケーションのすべての必要なファイルを置いてアップロードするという感じになります。今回はCドライブ直下にします。

c:\nkskbot

 最初に作るのはapp.yamlというアプリケーションの設定ファイルです。必ずこの名前にしてください。ここでアプリケーション名や実行されるスクリプトファイルを設定します。

application: nkskbot
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: nkskbot.py

applicationでアプリケーション名を指定し、runtimeで実行環境がPythonであることを指定します。handlersではURLと実行されるスクリプトの対応関係を指定します。ここでは'/'以下すべてのURLでnkskbot.pyが呼ばれます。この部分は正規表現で指定可能です。最初はこれだけで十分です。

  • nkskbot.py

 いわゆるBotの本体です。ここにBotの動作を記述します。はじめの一歩として、指定したURLにアクセスするとTwitterにPostするという処理をさせます。以下にその骨組みとなるスクリプトを示します。

#!-*- coding: utf8 -*-

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hello, webapp World!')

application = webapp.WSGIApplication(
                                     [('/', MainPage)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

ここで重要なのは"[('/', MainPage)]"の部分で、'/'にアクセスしたらMainPageクラスのget()が実行されるということです。get()があるからにはpost()もあるけど、今回使うのはget()だけです。次にそれを改良してBotにPostさせます。

import urllib
from base64 import b64encode
from google.appengine.api import urlfetch

class NkskPost(webapp.RequestHandler):
  def get(self):
    url = "http://twitter.com/statuses/update.xml"
    username = TwitterのID
    password = パスワード
    message = "キュフフ!"
    payload = urllib.urlencode({'status': message.encode("utf-8")})
    base64string = b64encode("%s:%s" % (username, password))
    headers = {"Authorization": "Basic %s" % base64string}
    urlfetch.fetch(url, payload=payload, method=urlfetch.POST, headers=headers)

これらの行をnkskbot.pyに追加します。新しくNkskPostクラスを作りました。ひとつの処理(リクエスト)に対してひとつのクラスを作成するという感じにします。get()の中はなんとなくしかわからないけど
http://handasse.blogspot.com/2008/06/google-app-engine-twitter.html
を参考にしました(というかコピペです)。そして重要なのがURLマッピングです。

application = webapp.WSGIApplication(
                                     [('/', MainPage),
                                     ('/post', NkskPost)],
                                     debug=True)

と変更します。どうしてこうなのかはなんとなく察してください。

  • テスト

 これでローカルでテストしてみます。いきなりアップロードはダメですよね。GAEではローカルでテストするためにSDKにサーバがついています。コマンドプロンプトで以下のように打ちます。

dev_appserver.py c:\nkskbot

これでhttp://localhost:8080/にアクセス。Helloなんちゃらと表示されれば成功。次にhttp://localhost:8080/postにアクセスです。なんも表示されない? なにか文字が出てきたらエラーです。ちょっとTwitterのページに行ってPostされたか確認します。エラーが出たらエラーメッセージを頼りにコードを修正して、もう一回ブラウザでアクセスの繰り返しです。サーバはずっと起動したままでデバッグできます。なお、コードに間違いがなくてもエラーが出ることもたまにあります。そこはそれであきらめましょう。

  • アップロード

 アップロードもSDK付属のスクリプトでできます。

appcfg.py update c:\nkskbot

Gmailアドレスとパスワードを求めてくるので入力します。成功したら、ブラウザでアクセス。URLは
http://アプリケーション名.appspot.com/
です。今回の場合はttp://nkskbot.appspot.com/ (実際にはないです)。 ttp://nkskbot.appspot.com/postにもアクセスしてみてPostできるか確認してみます。Postが確認できたら最初のステップは成功。

  • cron

 次のステップとしてBotらしくするために定期的にPostさせることにします。今のところは手動でURLにアクセスしないとPostできないんですが、これを自動的にリクエストを発してPostさせるようにします。GAEでは、定期的な処理のためにcronが提供されています。
http://code.google.com/intl/ja/appengine/docs/python/config/cron.html
cronはcron.yamlで設定します。

cron:
- description: nksk every hours post
  url: /post
  schedule: every 1 hours

descriptionに処理の説明、urlで処理を行うアプリケーションを呼び出すURL、scheduleでcronのスケジュールを指定します。スケジュールフォーマットはいろいろな形があるのでリンク先を読んでみてください。
 cronにはひとつだけ注意点があります。定期的な処理といっても所詮はURLなので誰でもアクセスできます。たとえば赤の他人の誰かが'/post'にアクセスしてアプリケーションを実行できたら、それは定期的な処理ではなくなってしまいます。そこでGAEではcron処理のURLには管理者アカウントでしかアクセスできないようになっています(ここらへん曖昧な理解)。普通にアクセスするとダメなんですが、cron.yamlによって出されたリクエストは管理者権限を持っているので、アプリケーションが実行されて定期的な処理が可能となります。その、管理者のみアクセス可能となるように設定するためにapp.yamlを編集します。

application: nkskbot
version: 1
runtime: python
api_version: 1

handlers:
- url: /post
  script: nkskbot.py
  login: admin
- url: /
  script: nkskbot.py

'/post'にアクセスするためには管理者権限が必要だよということで'login: admin'を追加します。'/'はそのままで誰でもアクセスできます。これでhttp://localhost:8080/postにアクセスしようとすると変なダイアログが出てくると思います。チェックしてログインすると実行されるはずです。cronが時間通りに動くかはわからないけど、それ以外でエラーがないようだったらアップロードします。後は待つだけです。

  • 管理

 アップロードした後は以下のリンクから管理コンソールにアクセスすることができます。
http://appengine.google.com/
そこでアクセスがどのくらいあったかとか、cronが正常に動いているかとか知ることができます。

  • まとめ

 というわけで、駆け足でしたがGAEを用いたTwitterBotの作り方をまとめてみました。cronと管理者権限の部分はかなり怪しいです。あと難しい機能だけど、強制停止URLがあったりすると、いざ暴走したときに便利です(泣)。もっと改良していけば@発言に対してReplyすることもできるようになります。というか、現状のなかさきBotはReplyしかできないように設定しています(先日暴走したので……)。
 なかさきBotの今後の育て方として、できればTLの流れを読み取って、それに合わせた発言をさせるようにしたいんですけどね。Yahoo!あたりのサービスを使ってなんか面白いやつに育てていきたいです。