Streaming APIで取得したつぶやきの処理方法


かつて、Streaming APIで大量のつぶやきをリアルタイムに「保存する方法」を紹介しました(cURL編Python編)。つぶやきはJSON形式で保存していましたが、そこから何かを見出すためにはまず、JSON形式のデータを処理できなければなりません。ここではその方法を確認します。

Pythonで簡単に処理する方法を、@nokunoさんが紹介しています(Twitter Streaming APIの使い方)。cURLで取得したつぶやきは、1行に1つずつファイルに格納されるので、次のように1行ずつ取り出してJSONデータをパースすればいいようです(ここではtweet['text']、つまりつぶやきの本文だけを取り出しています)。

#!/usr/bin/env python
import sys, json
for line in sys.stdin:
    tweet = json.loads(line)
    if 'text' in tweet:
        print tweet['text'].encode('utf-8')

cURL編Python編でつぶやきを保存したファイルがresult.datだとすると、「python parse.py < ressult.dat」などとして本文だけを取り出すことができそうです。

Streaming APIのsample.jsonならこれでもいいのですが、filter.jsonを使うときには、条件に合うつぶやきが途絶えることがあります。そういうときには、30秒ごとにCR LFが送信されてきて、それがファイルに書かれることになるので、上のように1行ずつ処理しようとすると、ValueErrorが発生して処理が途中で止まってしまいます(cURLの場合)。ですから、次のようにValueErrorを無視しなければなりません(PythonのコードではJSON形式だけを出力していたので問題ありません)。追記:Streaming APIが最初にfriendsを返すようになったので、それを無視するために、StandardErrorを無視することにしました。

#!/usr/bin/env python
import sys, json
#from pprint import pprint

for line in sys.stdin:
    try:
        tweet = json.loads(line)
        #pprint(tweet)
        #print type(tweet['text'])
        print tweet['text'].encode('utf-8')
    except StandardError:
        pass

入力がstr型でも出力の一部はunicode型になったりするのが紛らわしい。Pythonを使うのはバージョン3が主流になってからにしたいですね、細かいことですが。

つぶやかれた日時はtweet['created_at']で取得できるのですが(このあたりのことはpprint()で確認できます)、この値は「Thu Dec 29 04:27:28 +0000 2011」のように標準時なので、日本ではちょっと使いにくいです。そこで、日本時間の年月日時分秒(20111231000000)のような表現に変換する関数を用意します。

#!/usr/bin/env python
import sys, json, time, calendar
#from pprint import pprint

def YmdHMS(created_at):
    time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
    unix_time = calendar.timegm(time_utc)
    time_local = time.localtime(unix_time)
    return int(time.strftime("%Y%m%d%H%M%S", time_local))

for line in sys.stdin:
    try:
        tweet = json.loads(line)
        #pprint(tweet)
        print YmdHMS(tweet['created_at']), tweet['text'].encode('utf-8')
    except StandardError:
        pass

リツイートを除外したいときは、次のようにすればいいでしょう。

for line in sys.stdin:
    try:
        tweet = json.loads(line)
        #pprint(tweet)
        if 'retweeted_status' not in tweet:
            print YmdHMS(tweet['created_at']), tweet['text'].encode('utf-8')
    except StandardError:
        pass

cURL編で書いたように、こういうことをしているのは、Ustreamなどで配信された動画の整理のためなので、保存したつぶやきは、時間を指定してとりだせるようにしておきましょう。

以下のようなスクリプト(parse.py)を使えば、「python parse.py 20111230150000 20111230174600 < result.dat」などとして、日本時間の2011年12月30日15時から2011年12月30日17時46分までのつぶやきだけを取得できます(日時の指定は省略してもかまいません)。

#!/usr/bin/env python
import sys, json, time, calendar
#from pprint import pprint

def YmdHMS(created_at):
    time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
    unix_time = calendar.timegm(time_utc)
    time_local = time.localtime(unix_time)
    return int(time.strftime("%Y%m%d%H%M%S", time_local))

argv = sys.argv
start_time = 0
end_time = 99999999999999
if 1 < len(argv):
    start_time = int(argv[1])
    end_time = int(argv[2])

for line in sys.stdin:
    try:
        tweet = json.loads(line)
        #pprint(tweet)
        if 'retweeted_status' not in tweet:
            tweet_time = YmdHMS(tweet['created_at'])
            if start_time <= tweet_time and tweet_time <= end_time:
                tweet_sec = tweet_time-start_time
                screen_name = tweet['user']['screen_name']
                text = tweet['text'].encode('utf-8')
                url = "https://twitter.com/#!/%s/status/%s"\
                    % (screen_name, tweet['id_str'])
                #print tweet_sec, url, text
                #print text
                t = time.strptime(str(tweet_time), "%Y%m%d%H%M%S")
                print time.strftime("%H:%M:%S", t), text
    except StandardError:
        pass

どのような形式で出力するかは、後で何に使いたいかで決まります。たとえばyouTube上でキャプションを付けたいなら、YouTubeがサポートする形式(参考)にあわせるといいでしょう。

実際に、「#iwakamiyasumi」というハッシュタグで検索し保存したつぶやきのうち、「年末特番 ジャーナリスト休業直前!上杉隆氏ラストインタビュー」の配信時間中(2011年12月30日15:00から17:45)のものを抜き出すと下のようになります(スクロールバーを表示できない環境では閲覧できないかもしれません)。

Streaming APIで取得したつぶやきの処理方法” への1件のコメント

  1. ValueErrorの処理と時間の変換、めちゃくちゃ参考になりました。
    ベリーサンキューベリマッチョです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です