かつて、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)のものを抜き出すと下のようになります(スクロールバーを表示できない環境では閲覧できないかもしれません)。