Tumblr::Stat
自分のpost/reblogの統計をちょっととってみようかと。項目としては、
- 総 post/reblog 数 / 日毎推移
- posted by: 誰の元ポストを reblog しているか
- reblogged from: 誰の post/reblog を reblog しているか
- reblogged by: 誰に reblog されているか
- reblog/follower overlap: 。。。ちょっと説明しにくいが、自分の reblog した post を誰が reblog しているか
http://d.hatena.ne.jp/myhoney0079/20090104/p1の焼き直しだけど、骨格としては:
require "rubygems" require "tumblr" require "open-uri" require "hpricot" module Tumblr class Stats class Result def show (out = STDOUT) out << "=== result ===\n" end end def initialize (user, key) @user = user; @key = key end def get_posts(num) [] end def get_stats(posts) return Result.new() end def run (num=-1) posts = get_posts(num) result = get_stats(posts) result.show end end # class Stats end # module Tumblr ################################################################ def run user = 'myhoney0079' key = 'xxxxxxxx' num = 100 (stats = Tumblr::Stats.new(user, key)).run(num) end run()
Tumblr::API 必須。key は dashboard のhtmlソース見て display_post_notes(id, key) を探す。
Tumblr::Stats が主クラス。run() を呼ぶと、get_posts() ですべての post (Tumblr::Data::Post)を取得し、それを get_stats(posts) に渡し、そこでごにょごにょする。
get_stats(n) では、posts.each し、それぞれの post の reblognote 見て reblog 履歴を取得し、posted_by, reblogged_from, reblogged_by などを解析し、ハッシュに入れる。その結果を Tumblr::Stats::Result オブジェクトにいれ、返す。そして表示。。。という流れ。
n で解析する post 数を指定。無指定あるいは負だと全 post。。。。その度ごとに全 post にアクセスして reblognote を取得していると負荷がかかるので、cache を実装予定。
get_posts()
def get_posts(num) uri = "#{@user}.tumblr.com" posts = [] Tumblr::API.read(uri) do |pager| l = pager.last_page ## yet: now getting all posts...l = (num / 20).to_i ?? l = 0 ## for debug 0.upto(l) do |i| print "getting post..(#{i+1}/#{l+1}pages)\n" pager.page(i).posts.each do |post| posts << post end end end return posts end
get_stats()
def get_stats(posts) print "getting stats...\n" result = Result.new() i = 0; n = result.num_posts = posts.size posts.each do |post| print "..analysing post '#{post.postid}' (#{i+1} / #{n})\n"; i += 1 note = Tumblr::Reblognote.new(post.postid, @key) result.posted_by[note.posted_by] += 1 result.reblogged_from[note.reblogged_from] += 1 unless note.posted_by == @user note.reblogged_by.each do |foo| result.reblogged_by[foo] += 1 end end return result end
渡された posts を each で回して、Tumblr::Reblognote オブジェクトを作り、解析。結果を Tumblr::Stat::Result オブジェクトに入れる。
Tumblr::Stat::Result
class Result attr_accessor :posted_by, :reblogged_by, :reblogged_from attr_accessor :num_posts def initialize @posted_by = Hash.new(0) @reblogged_by = Hash.new(0) @reblogged_from = Hash.new(0) @num_posts = 0 end def show (out = STDOUT) out << "=== result ===\n" p @posted_by, @reblogged_from, @reblogged_by end end
必要な情報の accessor を用意するだけ。show() は、sort するなりなんなり。
Tumblr::Reblognote
module Tumblr class Reblognote class Item attr_accessor :action, :actor, :from def initialize(action, actor, from) @action = action; @actor = actor; @from = from end end # class Item def initialize(id, user, key) @id = id; @user = user; @key = key @uri = "http://www.tumblr.com/dashboard/notes/#{id}/#{key}" @notes = [] get_notes() end def posted_by return @notes[@notes.size-1].actor end def reblogged_from @notes.each do |item| print " check rf: #{item.actor} #{item.action} from #{item.from}\n" if item.action == "reblogged" and item.actor == @user print " ..u reblogged from #{item.from}\n" return item.from end end return nil end def reblogged_by ["a", "b", "c"] ## to be implemented end private def get_notes print "get url.. #{@uri}\n" (省略) return @notes end def method_missing(msg, *arg) @notes.send(msg, *arg) end end # class Reblognote
この前突貫で作ったやつの焼き直し。クラスにしただけ。ただ initialize() で http access するようにしちゃったけど、値参照時まで遅延させたほうがよいかも。