twitterの発言漏れをチェックするRubyスクリプト

ここ数日twitterでの発言漏れがひどいらしくて、自分の発言が特定のfollowerのtimelineに表示されないことがしばしば起こっている。
じゃあ一体誰のところで表示されていて、誰のところで表示されていないんだろうと思って、それを知るためのRubyスクリプトを書いた。あくまでも簡易的なものですが。要mechanize.
usernameとpasswordを変更するのを忘れずに。


4/22 3:15追記 重要
mechanizeの履歴を制限するのをすっかり忘れていました。
具体的には特に履歴が必要なければ @agent.max_history = 1 などのようにします。この設定をしないと(おそらく)すべてのページの履歴(Mechanize::Page)を記憶するので膨大なメモリを食います。
実際、僕の環境では最初のコードでは最大時で200MB以上のメモリを消費していました。上記のようにしただけで使用メモリは最大でも15MB以下に抑えられました。
ついついこの設定って忘れちゃんですよね。。。


4/22 3:55さらに追記
深夜に約200人をチェックした僕の場合で6分弱かかりました。かかる時間はチェックする人数に応じて大体これに比例すると考えられそうです。

require 'rubygems'
require 'mechanize'

class Chekker
  def initialize
    @agent = WWW::Mechanize.new
    @agent.user_agent_alias = 'Mac Safari'
    @agent.max_history = 1 #追記 重要!
    @username = 'username' #自分のusernameに変更
    @password = 'password' #自分のパスワードに変更
    login_form = @agent.get('http://twitter.com/').forms.first
    login_form['username_or_email'] = @username
    login_form['password'] = @password
    @agent.submit(login_form)
  end

  def check_post
    error_user = []
    product_set.each do |fl|
      begin
        friends_with = []
        friends_with = (@agent.get("http://twitter.com/#{fl}/with_friends")/"td.content"/:strong).map {|t| t.inner_text}
        error_user << fl if !friends_with.include?(@username)
      rescue WWW::Mechanize::ResponseCodeError => e
        case e.response_code
        when '404'
          next
        when '502'
          sleep 5
          retry
        end
      rescue Timeout::Error
        puts "WRYYY"
        sleep 5
        retry
      end
    end
    puts error_user
    if ARGV[0] == '-p'
      puts error_user.map {|u| '@' + u}.join(' ')
    end
  end

  private
  def lastpage_index(type)
    num = (@agent.get("http://twitter.com/#{type}")/:h2).inner_text.match(/\d+/).to_s.to_i
    (num%20) ? num/20 : num/20 + 1
  end

  def get_username(type)
    (1..lastpage_index(type)).inject([]) {|memo, i| memo + (@agent.get("http://twitter.com/#{type}?page=#{i}")/"a.url").map {|a| a.inner_text}}
  end

  def product_set
    get_username('followers') & get_username('friends')
  end
end

if __FILE__ == $0
  Chekker.new.check_post
end

やっていることは単純で、自分のfollowerかつ自分のfollowing(friend)であるユーザを求めて、彼らのページを個別に訪れ、with_othersに自分の発言が含まれているかをチェックしているだけ。つまり、with_othersには20件しか表示されない仕様なので、timelineの流れの速いfollowing(ものすごくたくさんの人をfollowしている人)のwith_othersには発言直後でも自分の発言が含まれないことがあることに注意してください。
自分の発言の30秒から1分後ぐらいにまわすのがいいかと。ただし、twitterのサイト状況によっては結構時間がかかったり、開始まもなくエラーが出るので気長にどうぞ。(早くても3分はかかるかも)
バグっているところや、コードに関するつっこみがあればよろしくお願いします。

使い方は

ruby chekker.rb -p

などとすればOK. -pオプションをつけると下のように、自分の発言が表示されていなかったユーザ一覧の最後に@つき空白区切りでユーザを並べます。-pオプションをつけなければ1行に1ユーザが表示されるだけです。

自分の発言に@をつけるとみんなに見えやすくなるというのも聞くので、twitterの中身はどうなっているか興味津々です。