twitterのように更新頻度が高いサービスのAPIはポーリングとあまり相性がよくありません。どうせtwitter API使うプログラム書くなら、リアルタイムなイベントベースっぽいAPIの方が色々と都合が良いので調べてみました。なんとなくXMPPに対応してる気がしてたんですが、実際はStreaming APIという独自のインターフェースが用意されていました。
Streaming API自体はただのHTTPリクエストで、リクエストのコネクションを張りっぱなしにして、都度データが流れてくる様な形になります。見るからに相性が良さそうなのでgeneratorで書いてみました。この例では幾つか種類があるStreaming APIの中からfilterを使っています。
#!/usr/bin/python # -*- coding: utf-8 -*- import sys import base64 import urllib import urllib2 from pit import Pit # tweetが流れる度にそのデータを返却するgenerator def read_stream_api(user, passwd, trackword): request = urllib2.Request('http://stream.twitter.com/1/statuses/filter.json') basic = base64.encodestring('%s:%s' % (user, passwd))[:-1] request.add_header('Authorization', 'Basic %s' % basic) postdata = urllib.urlencode({'track':trackword}) res = urllib2.urlopen(request, postdata) for line in res: if line.strip() is not "": yield line # Usage: # python streaming_test.py (filterするキーワード) # if __name__ == '__main__': trackword = sys.argv[1] config = Pit.get('twitter.com') user = config['username'] passwd = config['password'] stream = read_stream_api(user, passwd, trackword) while True: print stream.next()
実際に動かしてから解ったのですが、streaming apiは全てのtweetを取得できる訳ではなく、一定のアルゴリズムでサンプリングを行った結果を返却します。filterもサンプリングされたデータを更にフィルタリングするので、例えばfilterを利用して特定のキーワードを含むtweetを全て取得するというような用途には使えません。(実際は申請して認められれば使えるようですが。)思っていた挙動とは違いましたが、割と面白いインターフェースなので、活用方法を探したいですね。
また先日も使ったtweepyを使うともっとエレガントにStreaming APIを使えます。上記と同じ挙動をするサンプルが以下になります。短くていい感じですね。
#!/usr/bin/python # -*- coding: utf-8 -*- import sys import tweepy from pit import Pit class StreamListener(tweepy.StreamListener): def on_data(self, data): print data def main(): conf = Pit.get('twitter.com') user = conf['username'] passwd = conf['password'] stream = tweepy.Stream(user, passwd, StreamListener()) stream.filter(track=[sys.argv[1]]) if __name__ == "__main__": main()
今のところtweepyがpython用のtwitterラッパーとしては最強なんじゃないかと思うんで、twython使ってる人は乗り換えたら良いと思いますYO!




