Skip to content

Twitter で Unfollowers (アンフォローをした方)をチェックする簡易スクリプト

Posted on:2009年11月7日 at 16:01

Table of Contents

Open Table of Contents

スクリプトを準備した経緯

Twitter を始めて早 2 ヶ月が経とうとしている。

「Google Reader なんかもういらない!」(Rest in Peace, RSS)という記事に触発されて始めてみたのだが、自分自身には相変わらず Google Reader は必需品だ。。(用途の棲み分けはできている)

ただ、これまで触れ合うことはなかった方々と触れ合えたり、Google Reader と合わせて貴重な情報源となっており、今では Twitter も必需品だ。

そんな中、「Twitter で Unfollowers (アンフォローをした方)を調べるにはどうしたらいいの?」という質問を受けた。

現状身近な方には特に知らせることも無く、こっそり静かに Twitter を使っているのだが、自身の follower さんも少しづつ増えてきている。
この follower さん、増えるだけでは無く、当然ながら減ることもある。フォローされた場合は、メール通知の設定をしておけば、メールで知ることができるが、確かに、一度フォローした後、そのフォローを解除している方を知るための機能は標準では無さげだ。(きっと)

標準では無さそうだが、同様のことをしてくれるサービスは既にあるだろう。車輪の再開発だが、Twitter のサードパティのサービス/アプリは多すぎて、、、簡単なものであれば自分で準備した方が手軽だ。

しかし、もしかすると、これからやろうとしていることはパンドラの箱なのかもしれない。。
例えば、妻のアカウントからフォローされていたのに、ある日突然そのフォローが外れていたら、どう対応すればよいのだろう・・・知らぬが仏のような気もする。。

Unfollowers をチェックするスクリプト

まずは、Twitter API とやり取りを行うベースとなる簡易 Twitter クライアントを用意する。適当な名前付けでSimpleTwitterとする。

SimpleTwitter

httparty gem がインストールされていない場合には、事前にインストール。

$ sudo gem install httparty
$ gem list httparty

*** LOCAL GEMS ***

httparty (0.4.3)

今回の目的からは外れるが、Timeline の表示、Mention の表示も一応入れておく。

simple_twitter.rb

require 'time'
require 'forwardable'

require 'rubygems'
require 'httparty'

class SimpleTwitter
  extend Forwardable
  include HTTParty
  base_uri 'https://twitter.com' # SSL

  def_delegator :"#{self}", :get, :get

  def initialize(user, password, options = {})
    if options.key? :http_proxy
      options[:http_proxy_port] ||= 8080
      self.class.http_proxy options[:http_proxy], options[:http_proxy_port].to_i
    end
    @auth_info = { :username => user, :password => password }
  end

  def timeline(which = :friends, options = {})
    auth_info_merge! options
    get("/statuses/#{which}_timeline.json", options)
  end

  def mentions(options = {})
    auth_info_merge! options
    get("/statuses/mentions.json", options)
  end

  def followers(options = {})
    auth_info_merge! options
    options[:query] ||= {}
    options[:query].merge!({ :cursor => -1 }) unless options[:query].key? :cursor
    get("/statuses/followers.json", options)
  end

  class << self
    def format_time(time, format = '%Y/%m/%d %H:%M:%S')
      (time.is_a?(String) ? Time.parse(time) : time).strftime(format)
    end
  end

  private
  def auth_info_merge!(options)
    options.merge!({ :basic_auth => @auth_info })
  end
end

タイムラインの表示などには、以下のような感じで使える。

require 'simple_twitter'

twitter = SimpleTwitter.new('user', 'password')
# for Proxy
# twitter = SimpleTwitter.new('user', 'password',
#   { :http_proxy => 'proxy_server', :http_proxy_port => 8080 })

# query count default 20
twitter.timeline(:friends, { :query => { :count => 5 } }).each do |twit|
  puts "#{twit['user']['screen_name']} [#{SimpleTwitter.format_time(twit['created_at'])}](#{twit['id'].to_s}):\n" +
       "  #{twit['text']}"
end

表示は以下のような感じ。

# >> delicious50 [2009/11/07 15:47:58](5501187604):
# >>   ALC http://bit.ly/lcfEp japan
# >> delicious50 [2009/11/07 15:47:56](5501187311):
# >>   findability.org - by Peter Morville http://bit.ly/15KKUP findability ia
# >> GuyKawasaki [2009/11/07 15:46:52](5501173816):
# >>   Guess who is a Glamour woman of the year? http://om.ly/bTqX
# >> tek_news [2009/11/07 15:46:49](5501173203):
# >>   HNews: Someone actually created a pyramid scheme for Twitter popularity. http://bit.ly/20gVa5
# >> GuyKawasaki [2009/11/07 15:46:46](5501172663):
# >>   The official rules of Shotgun http://om.ly/bTqU

Unfollowers をチェックするスクリプト

follows_unfollowers_check.rb

require 'simple_twitter'

FOLLOWERS_CSV = 'followers.csv'
INDENT = ' ' * 2

def get_follower_user_list(twitter, cursor = -1)
  users = []
  twit_followers = twitter.followers(:query => { :cursor => cursor })

  twit_followers['users'].each do |follower|
    users << follower['screen_name']
  end

  next_cursor = (twit_followers['next_cursor'] ||= '0')
  unless next_cursor.to_i == 0
    users.concat(get_follower_user_list(twitter, next_cursor))
  end
  users
end

twitter = SimpleTwitter.new('user', 'password')
# for Proxy
# twitter = SimpleTwitter.new('user', 'password',
#   { :http_proxy => 'proxy_server', :http_proxy_port => 8008 })

current_users = get_follower_user_list(twitter)

previous_users = []
if File.exist? FOLLOWERS_CSV
  begin
    previous_users = File.open(FOLLOWERS_CSV).read.split(',')
  rescue
    puts $!
    exit(9)
  end
end

unfollowers = previous_users - current_users
new_follow_users = current_users - previous_users

puts "Follow User Stats at #{SimpleTwitter.format_time(Time.now)}"
puts '=' * 50
puts "Current Follow Users count: %s" % current_users.size.to_s
puts "Unfollowers count: %s" % unfollowers.size.to_s

unfollowers.each do |user|
  puts "#{INDENT}#{user}\t#{SimpleTwitter.base_uri}/#{user}"
end

puts "New follow Users count: %s" % new_follow_users.size.to_s

new_follow_users.each do |user|
  puts "#{INDENT}#{user}\t#{SimpleTwitter.base_uri}/#{user}"
end

File.open(FOLLOWERS_CSV, 'w') { |f| f.write current_users * ',' }

結果は以下のような出力になる。(Emacs 上で rcodetools を利用した際の表示)

# >> Follow User Stats at 2009/11/07 15:03:01
# >> ==================================================
# >> Current Follow Users count: 65
# >> Unfollowers count: 7
# >>   SavvyExplorer     https://twitter.com/SavvyExplorer
# >>   talyaalove        https://twitter.com/talyaalove
# >>   59minlearning     https://twitter.com/59minlearning
# >>   lifefulfillment   https://twitter.com/lifefulfillment
# >>   follow4profit     https://twitter.com/follow4profit
# >>   Forex_Blog        https://twitter.com/Forex_Blog
# >>   VirtualTotte      https://twitter.com/VirtualTotte
# >> New follow Users count: 6
# >>   RecognitionApps   https://twitter.com/RecognitionApps
# >>   kazuyo_k          https://twitter.com/kazuyo_k
# >>   Dewina_Olivera    https://twitter.com/Dewina_Olivera
# >>   HP_AppSecurity    https://twitter.com/HP_AppSecurity
# >>   videotodaynews    https://twitter.com/videotodaynews
# >>   devtube           https://twitter.com/devtube

実行は、simple_twitter.rbfollows_unfollowers_check.rb を同じディレクトリにおいておいて、

$ ruby ./follows_unfollowers_check.rb

前回スクリプトを動かした時との差分が表示される。

正確にやろうと思うと、細目にこのスクリプトを動かしておかないといけない。前回動作時との間に follow/unfollow の両方を行ったアカウントは捉えられないので。
また、結果の出力は標準出力以外のもの、メールでの送信などにしておくのもよいかもしれない。