2013年9月3日火曜日

TwitterのストリーミングAPIを試してみた

Twitterからリアルタイムに情報を得るStreaming APIを試してみました。
$ sudo easy_install pip
$ sudo pip install tweepy --upgrade
として、パッケージ管理ツール pip をインストールした後、tweepy をアップグレードしました。その後、キーワードを含む tweet を入手するスクリプトをいろんなところを参考にしながらなんとか作りました。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import json
import tweepy  
import re

# Account 
consumer_key= '  '
consumer_secret= ' '
access_token= ' '
access_token_secret= ' '

class Listener(tweepy.streaming.StreamListener):
    def on_data(self, data):
        if data.startswith("{"):
            tweet = json.loads(data)
            if 'text' in tweet:
                user = tweet['user']
                text = re.sub(r'\n',r' ',tweet['text'].encode('utf-8')) # 改行コード除去
                print tweet['id'],":",tweet['lang'],":",user['screen_name'].encode('utf-8'),":", \
                              user['name'].encode('utf-8'),":", text
        return True

    def on_error(self, status):
        print status

if __name__ == '__main__':
    l = Listener()
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)

    stream = tweepy.Stream(auth, l)
#    filterの宣言部分 @ /usr/local/lib/python2.7/dist-packages/tweepy/streaming.py
#    def filter(self, follow=None, track=None, async=False, locations=None, 
#        count = None, stall_warnings=False, languages=None):
#    パラメータの使い方は https://dev.twitter.com/docs/streaming-apis/parameters
    stream.filter(languages=['ja'],track=['AKB', 'HKT', 'NMB'])
15~27行目がデータ受信時の処理で、データを分析してユーザー名やscreeen_name、tweetの内容などを表示します。29行目からが認証で、34行目でstreaming apiを呼び出しています。
39行目でフィルタの内容を設定していて、ここでは日本語のTweetで、「AKB,HKT,NMB」を含むものをキーワードとしています。キーワードは日本語のようなスペース区切りではない言語では正常に動作しないようです。
同じ処理は、on_data ではなく、 on_statusを使うとJSONの解析もTweepy側でやってくれるようで、on_status版も上げておきます。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import json
import tweepy  
import re

# Account
consumer_key= ' '
consumer_secret= ' '
access_token= ' '
access_token_secret= ' '

class Listener(tweepy.streaming.StreamListener):
    def on_status(self, status):
        print status.id,":", \
               status.lang,":", \
               status.user.screen_name.encode("utf-8"),":", \
               status.user.name.encode("utf-8"),":", \
               re.sub(r'\n',r' ',status.text.encode("utf-8"))
        return True

    def on_error(self, status):
        print status

if __name__ == '__main__':
    l = Listener()
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)

    stream = tweepy.Stream(auth, l)
#    filterの宣言部分 @ /usr/local/lib/python2.7/dist-packages/tweepy/streaming.py
#    def filter(self, follow=None, track=None, async=False, locations=None, 
#        count = None, stall_warnings=False, languages=None):
#    パラメータの使い方は https://dev.twitter.com/docs/streaming-apis/parameters
    stream.filter(languages=['ja'],track=['AKB', 'HKT', 'NMB'])
取得できるデータは、あるtweetを参考に分析してみたところ、
{u'contributors': None,
 u'truncated': False,
 u'text': u'\u301017\u6642....00#NMB #HKT48\u3000#HKT',
 u'in_reply_to_status_id': None,
 u'id': 3744....11520,
 u'favorite_count': 0,
 u'source': u'<a href="http://twittbot.net/" rel="nofollow">twittbot.net</a>',
 u'retweeted': False,
 u'coordinates': None,
 u'entities': {u'symbols': [],
               u'user_mentions': [],
               u'hashtags': [{u'indices': [68, 74], u'text': u'AKB48'},
                             {u'indices': [75, 79], u'text': u'AKB'},
                             {u'indices': [80, 86], u'text': u'SKE48'},
                             {u'indices': [87, 91], u'text': u'SKE'},
                             {u'indices': [92, 98], u'text': u'NMB48'},
                             {u'indices': [99, 103], u'text': u'NMB'},
                             {u'indices': [104, 110], u'text': u'HKT48'},
                             {u'indices': [111, 115], u'text': u'HKT'}],
               u'urls': [{u'url': u'http://t.co/f4....w6kL', u'indices': [8, 30], u'expanded_url': u'http://com.nicovideo.jp/community/co....411', u'display_url': u'com.nicovideo.jp/community/co....\u2026'}]},
 u'in_reply_to_screen_name': None,
 u'id_str': u'3744....1520',
 u'retweet_count': 0,
 u'in_reply_to_user_id': None,
 u'favorited': False,
 u'user': {u'follow_request_sent': None,
           u'profile_use_background_image': True,
           u'default_profile_image': True,
           u'id': 63.....87,
           u'verified': False,
           u'profile_image_url_https': u'https://.......png',
           u'profile_sidebar_fill_color': u'DDEEF6',
           u'profile_text_color': u'333333',
           u'followers_count': 1,
           u'profile_sidebar_border_color': u'C0DEED',
           u'id_str': u'63.....87',
           u'profile_background_color': u'C0DEED',
           u'listed_count': 0,
           u'profile_background_image_url_https': u'https://......png',
           u'utc_offset': 32400,
           u'statuses_count': 25632,
           u'description': None,
           u'friends_count': 1,
           u'location': u'',
           u'profile_link_color': u'0084B4',
           u'profile_image_url': u'http://......png',
           u'following': None,
           u'geo_enabled': False,
           u'profile_background_image_url': u'http://......png',
           u'name': u'\u308a\u3063..........\uff09',
           u'lang': u'ja',
           u'profile_background_tile': False,
           u'favourites_count': 0,
           u'screen_name': u'KK....ty',
           u'notifications': None,
           u'url': None,
           u'created_at': u'Sun Jul 15 18:..:.. +0000 2012',
           u'contributors_enabled': False,
           u'time_zone': u'Osaka',
           u'protected': False,
           u'default_profile': True,
           u'is_translator': False},
 u'geo': None,
 u'in_reply_to_user_id_str': None,
 u'possibly_sensitive': False,
 u'lang': u'ja',
 u'created_at': u'Mon Sep 02 08:..:.. +0000 2013',
 u'filter_level': u'medium',
 u'in_reply_to_status_id_str': None,
 u'place': None}
というような感じで、ユーザー名などは入れ子になったデータ構造になっていますので、on_data版ではソースの20行目のように一旦'user'データを取り出しています。

0 件のコメント: