twitterのfollowingを増やすためのツールつくったー
twitterをはじめて少しはfollowしたけどなんとも誰を追加したらいいかわからない俺のためにfollow候補を見つけ出すツールを作ったよ。
このツールをぶん回すと、自分がfollowしている人のfollowしている人たちをがばっととってきて、多くfollowされている人を順に表示するよ。つまり、友達みんなが友達にしている人なら楽しいに違いないからfollowして僕と握手だ!というのを実現するのです!
使い方 ./scriptname.rb USER_NAME PASSWORD [OUTPUT_FILENAME]
ちなみに、twiiterが重いのとかいろいろなことによって、お友達のお友達を集めてくるのに超絶時間がかかります!なにこれ!かかりすぎ!このままだととっても気の長い人しか使えないよ!
あと、自分のfollowingのページをダウンロードしてきてそれを雛形にfollow候補リストを作成するのですが、ローカルにある関係上か、followボタンを押してもfollowされません。名前をくりっこしてその人のページにアクセスしてfollowしてね!ローカルに出来上がったファイルからばしばしとfollowしていきたいところですが、Javascriptとかぜんぜんわからないからなんともできない!教えて偉い人!
require 'rubygems' require 'hpricot' require 'open-uri' require "rexml/document" require 'net/http' Net::HTTP.version_1_2 class TwitFriends < Array VERSION = '0.0.2' TW_HOME = 'http://twitter.com/' TW_FRIENDS = 'http://twitter.com/friends' TWAPI_FRIENDS = 'http://twitter.com/statuses/friends.xml' TIME_INTERVAL = 10 MAX_PAGE = 1000 TMP_DIR = './tmp/' class TwitterUser def initialize(user, html=nil) @user = user @html = html @friends = end def size @friends.size end def friends_url TW_HOME + @user + '/friends' end def friends_path '/' + @user + '/friends' end attr_accessor(:user, :html, :friends) end class TwitterUsersList < Hash def add(user, friend) if self[user.user].nil? then self[user.user] = user end self[user.user].friends << friend self end def to_s str = '' self.each do |name, user| str << name + ': ' + user.friends.join(', ') + "\n" end str end end class WrongPasswordError < StandardError; end def initialize(user, pass) Dir.mkdir(TMP_DIR) if !FileTest.directory?(TMP_DIR) crypt_pass = 'Basic ' + [user + ':' + pass].pack('m') @tw_auth = {'Authorization' => crypt_pass} @template = nil @tw_login_name = user @tw_login_pass = pass open(TW_FRIENDS, @tw_auth){|f| @template = Hpricot(f) } end def get_my_users return @friends if @friends @friends = xml = nil begin open(TWAPI_FRIENDS, @tw_auth){|f| xml = REXML::Document.new(f)} rescue OpenURI::HTTPError print $!, ". wait and retry ...\n" sleep(10) retry end xml.elements.each('/users/user') do |ele| @friends << TwitterUser.new(ele.elements['screen_name'].text) end @friends end def tmp_file_name(name, page) TMP_DIR + name + '_' + page.to_s + '.html' end def save_html(name, page, body) File.open(tmp_file_name(name, page), "w") do |f| f.print body end end def saved?(user, page) if FileTest.exist?(filename = tmp_file_name(user.user, page)) then html_body = '' File.open(filename) do |f| html_body << f.read end return html_body end nil end def get_page(http, user, page) if tmp = saved?(user, page) then return tmp end http_req = Net::HTTP::Get.new(user.friends_path + "?page=" + page.to_s) http_req['Connection'] = 'Keep-Alive' http_req.basic_auth(@tw_login_name, @tw_login_pass) sleep(TIME_INTERVAL) begin res = http.request(http_req) http_body = res.body case res.code when "302" then raise WrongPasswordError end rescue case $! when WrongPasswordError then print $!, ". id or password is wrong.\n" exit else print $!, "\nrestart http...\n" http.finish sleep(10) http.start retry end end save_html(user.user, page, http_body) http_body end def get_friends list = TwitterUsersList.new uri = URI.parse(TW_HOME) Net::HTTP.start(uri.host) do |http| print "getting #{@tw_login_name}'s friends...\n" get_my_users.each do |user| counter = 0 while(true) do counter += 1 print ' ' * 78 + "\r" print "getting #{user.user}'s page #{counter} ..." page = Hpricot(get_page(http, user, counter)) page.search("tr.vcard").each do |html| html = Hpricot.parse(html.inner_html) name = html.search("a.uid").inner_html.gsub(/<[^>]*>/, '') list.add(TwitterUser.new(name, html), user) end break if page.search("a[@rel='me next']").empty? break if counter > MAX_PAGE print "done. \r" end print "\n" end end self.replace(list.keys.sort{|a,b| list[b].friends.size <=> list[a].friends.size }.map{|name| [name, list[name], list[name].friends.size] }) end def output_html(filename = 'out.html') get_friends @template.search("tr.vcard").remove str = '' self.each do |obj| str << '' str << obj[1].html.to_html str << ' ' str << '' end @template.search("table.doing").prepend(str) File.open(filename, "w") do |f| f.print @template.to_html end end end if $0 == __FILE__ then user = ARGV.shift; pass = ARGV.shift; output = ARGV.shift; if user.nil? or pass.nil? then print "use: ./#{$0} USER PASS [OUTPUT_FILE]\n" exit end TwitFriends.new(user, pass).output_html(output) end ' + obj[2].to_s + ': ' str << obj[1].friends.map{|friend| '' + friend.user + '' }.join(', ') str << '
open-uri使ったりNet::HTTP使ったり「user」だったり「name」だったりして超汚いので俺の適当具合がよく分かる完成度となっております!