TornadoとChirpUserStreamsでTweetの流れを眺める

http://apiwiki.twitter.com/ChirpUserStreamsを使うと、自分がfollowしているユーザのイベント(つぶやき、RT、ふぁぼ、followなど)の情報を取得出来る。

以前、Twitter Streaming APIでTweetの流れを眺める - DiaryExceptionではtwisted.web.clientを使ってStreamingを取得したが、今回は、FriendFeedで用いられているTornadoというWebアプリケーションフレームワークの機能を使って、Streamingを取得する。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import tornado.httpclient
import tornado.escape  # JSONのデコード
import urllib

user = 'YOUR_TWITTER_ID'
password = 'YOUR_PASSWORD'
url = "http://chirpstream.twitter.com/2b/user.json"  # ChirpUserStreams
# url = "http://stream.twitter.com/1/statuses/sample.json"  # Streaming

def splitAt(lst, n):  # 文字列をn文字毎に改行する
    result = []
    for i in range(len(lst)/n + 1):
        result.append(lst[i*n:(i+1)*n])
    return result

user_url = "http://twitter.com/users/show/%s.json"
status_url = "http://api.twitter.com/1/statuses/show/%s.json"

def callback(line):
    if line.strip() is not "":
        try:
            elems = tornado.escape.json_decode(line.strip())
            event = ""
            if 'friends' in elems:  # streamに繋ぐとまず自分がfollowしているユーザのIDが流れてくる
                print line
            elif 'delete' in elems:  # 誰かtweetを消した
                user_id = elems['delete']['status']['user_id']
                u_elems = tornado.escape.json_decode(urllib.urlopen(user_url % user_id).read())
                print "%s >> (delete tweet)" % (u_elems['screen_name'])
            elif 'event' in elems:
                t_elems = tornado.escape.json_decode(
                    urllib.urlopen(user_url % elems['target']['id']).read())
                s_elems = tornado.escape.json_decode(
                    urllib.urlopen(user_url % elems['source']['id']).read())
                print "%s >> (%s) >> %s" % (  # 誰かが誰かに対して何かeventを起こした
                    s_elems['screen_name'], elems['event'], t_elems['screen_name'])
                if elems['event'] == "favorite":  # ふぁぼった
                    txt_elems = tornado.escape.json_decode(urllib.urlopen(
                            status_url % elems['target_object']['id']).read())
                    print "  " + "\n  ".join(splitAt(txt_elems['text'], 40))
            else:  # 通常のtweet
                print "%s\n  %s" % (
                    elems['user']['screen_name'], "\n  ".join(splitAt(elems['text'], 40)))
        except ValueError:
            # print line
            pass
    else:
        pass

if __name__ == "__main__":
    http_client = tornado.httpclient.HTTPClient()
    try:
        request = tornado.httpclient.HTTPRequest(url,
            streaming_callback=callback,
            auth_username=user, auth_password=password,
            connect_timeout=0, request_timeout=0)
        http_client.fetch(request)
    except tornado.httpclient.HTTPError, e:
        print "Error:", e

HTTPに特化したものであれば、TwistedよりもTornadoを使った方が簡単に書けると感じた。