Wassr クラス: タイムラインを取得する
対象のユーザや自分のタイムラインを取得するために作った Wassr クラスです。
今のところタイムラインを取得するくらいしかできません。
CodeRepos に上げてみようかな。
require 'rubygems' require 'mechanize' require 'hpricot' # TODO: クラスごとにファイルに分ける gtaka555 # TODO: timeline の取得処理にコードのダブりを調整 gtaka555 class Wassr class Message attr_accessor :username, :message, :permalink, :date, :favorite def initialize @favorite = [] end end class Favorite attr_accessor :username end class API end def initialize @is_logined = false end # TODO: 認証処理 gtaka555 def login(username, passwd) @agent = WWW::Mechanize.new page = @agent.get('http://wassr.jp/') form = page.forms.name('LoginForm').first form.login_id = username form.login_pw = passwd @user_top_page = @agent.submit(form) @is_logined = true true end def timeline(limit_date = nil) messages = [] Wassr::walk_timeline_page(@agent, @user_top_page, limit_date) end # TODO: メソッドの再設計が必要 gtaka555 def self.public_timeline(username = nil, limit_date = nil) return [] if username.nil? agent = WWW::Mechanize.new # TODO: WWW::Mechanize の exception をとるように gtaka555 # TODO: close なユーザの場合のエラー処理 gtaka555 page = agent.get("http://wassr.jp/user/#{username}") Wassr::walk_timeline_page(agent, page, limit_date) end def self.walk_timeline_page(agent, page, limit_date = nil) messages = [] timeline_page = page while true m = Wassr::parse_html_page(timeline_page.body) messages.concat(m) # TODO: ページ移動中に発言が流れる可能性があるため、ユニーク処理が必要 gtaka555 next_link = timeline_page.links.find {|l| l.text =~ /Next/ && l.href =~ %r!^http://wassr.jp/my/\?page=!} if next_link.nil? break end # puts "debug: -> #{next_link.href}" # TODO: いらない日付の発言は切るように gtaka555 if !limit_date.nil? && m.last.date <= limit_date break end select(nil, nil, nil, 1.0) # => sleep 1 timeline_page = agent.click next_link end messages end def self.parse_html_page(html) messages = [] doc = Hpricot(html) (doc/"div[@class='OneMsg xfolkentry']").each do |elem| msg = Wassr::Message.new # TODO: HTML 要素がなかった場合のエラー処理 msg.username = elem.at("div.messagefoot_container > p.messagefoot > a.MsgUserName").inner_text # username msg.permalink = elem.at("div.messagefoot_container > p.messagefoot > a.MsgDateTime")[:href] # permalink msg.message = elem.at("p[@class='message description']").inner_text # message date = elem.at("div.messagefoot_container > p.messagefoot > a.MsgDateTime").inner_text # date favorite_elems = elem.at("div.favorite_list") unless favorite_elems.nil? (favorite_elems/"a").each do |favorite_elem| favorite = Wassr::Favorite.new favorite.username = favorite_elem[:title] msg.favorite << favorite end end msg.date = Time.parse(date) msg.message = msg.message.gsub(/(^\s+)|(\n$)|(\r\n$)/m, '') messages << msg end messages end end if $0 == __FILE__ require 'csv' #messages = Wassr::public_timeline('ゆーざめい', Time.parse("2008/09/29 00:00:00")) wassr = Wassr.new wassr.login('ゆーざめい', 'ぱすわーど') messages = wassr.timeline(Time.parse("2008/10/03 00:00:00")) CSV.open('timeline.csv', 'w') do |writer| messages.each do |message| writer << [message.date, message.username, message.message] end end end __END__ # # 2008/10/03 # * 'Next' リンクの抽出条件を変更 # # 2008/09/28 # * Wassr::Message に permalink, favorite を追加 # * Wassr::parse_html_page permalink, favorite の解析処理を追加 # * Wassr::Message message の末尾の改行を削除する処理を追加 # * Wassr::walk_timeline_page timeline ページを走査して解析するメソッドを追加 # * Wassr#new 追加 # * Wassr is_logined を追加 #