Twitter APIを使って、ハッシュタグを取得する。

追記(2012年2月24日)

たぶん、メソッドの使い方が違っている。

本文

twitterは流れが早すぎるのと、本家Twitterが現在から過去に向けて発言が流れるせいで、議論を追う気にならない。せっかく、#shiwake3や#f_o_sがおもしろそうなのに。

そこで、Twitter APIを使って、ハッシュタグの発言を過去に遡って取得し、それを自分の見やすい形に格納しやすいようにすることにした。このエントリーでは、Twitter APIを使ってあるハッシュタグがついた発言を遡るところまでを書く。

Ruby twitter gemのインストール

Ruby gemsを使ってインストールする。今回試した環境は以下のとおり。

まず、gemのアップデート

# update_rubygems
か
# gem1.8 update --system

次にtwitter gemのインストール

# gem1.8 install twitter

発言取得スクリプト(現在から過去)

以下のサイトを参考にスクリプトを考案。

注意すべき点は以下のとおり。

  • Twitter APIは、1度のアクセスで最大100件しか発言を返してくれない
  • Twitter APIは、最新から過去へ向かって発言を返してくる
  • あるIPアドレスからTwitter APIへアクセスできるのは1時間あたり100回まで(これは変動するらしい)

考えたスクリプトは以下のとおり。

$KCODE = "UTF-8"

# ハッシュタグの指定
tag = 'f_o_s'

# 取得する発言のidをこの変数で制限。初期値として、最新の発言idを設定
twit_status_id_max = 5916066331
flg = true 

# 後で時系列順にしたいので一度配列に格納
messageArray = Array.new

while(flg) do
  # このカウンターで発言が取得できなくなったことを判定する。
  counter = 0

  # max(id) で発言の新しさを制限する。
  Twitter::Search.new.hashed(tag).max(twit_status_id_max).per_page(100).each{|msg|
    tmpArray = Array.new
    localtime = Time.parse(msg.created_at).localtime

    # 最新の発言idから過去に向けてどんどん遡らせる。
    if msg.id <= twit_status_id_max
      twit_status_id_max = msg.id
    end

    tmpArray.push(msg.id.to_s,msg.from_user,msg.text.strip,localtime)
    messageArray.push(tmpArray)
    counter = counter + 1
  }

  # 何も画面にでないと怖いので進捗状況の表示
  puts twit_status_id_max.to_s+':'+counter.to_s
  if counter == 0
    flg = false
  end
  sleep(10)
end

# 取得した発言をCSVファイルで保存。
# Ruby標準のCSVライブラリは追記がないので
# http://d.hatena.ne.jp/unageanu/20080824/1219576777 のスクリプトを
# 利用させていただいている。

require "csv"

# 追記をサポートするように改造。
class << CSV
  alias_method( :open_org, :open )
  
  def open( path, mode, fs=nil, rs=nil, &block )
    if mode == "a" || mode == "ab"
      open_writer( path, mode, fs, rs, &block)
    else
      open_org( path, mode, fs=nil, rs=nil, &block )
    end
  end
end

# CSVファイルに出力
output_file = tag+'.csv'
CSV.open(output_file, 'a'){| writer |
  messageArray.reverse.each{| tmpArray |
    writer << tmpArray
  }
}

上記のスクリプトはあまりスマートではない。

  1. 発言が10,000件以上だと、途中で異常終了する(発言が取得できなかったときの例外処理を用意していないため)
  2. Twitterの最新発言のidが必要となる。
  3. ハッシュタグTwitterの最新発言のidがハードコーディング(スクリプト中に埋め込まれている)されている

発言取得スクリプト(新しい発言を追加で記録)

cronなどで回して、最新発言だけを取得したい場合は上のスクリプト

twit_status_id_max = 最新の発言id
Twitter::Search.new.hashed(tag).max(twit_status_id_max).per_page(100).each{|msg|
 〜省略〜
}

となっている部分を

twit_status_id_max = 前回取得した最新発言
Twitter::Search.new.hashed(tag).since(twit_status_id_max).per_page(100).each{|msg|
 〜省略〜
}

とすれば良いはず。あと、微調整が必要だけど。