buzzurl や del.icio.us のブックマーク件数を JSON で取得して表示する Ruby スクリプト

はてなブックマーク [2007-01-28]livedoor クリップ [2007-02-10] に続いて,buzzurldel.icio.us のブックマーク件数を取得する Ruby スクリプトを書いてみた.



API がなくて JSON しか提供されてないので,自分の生半可な知識では手のつけようがない.というわけで,JSON parser というのをありがたく頂戴してくる.

まず,buzzurl 用は以下.

#!/usr/bin/ruby
#http://webos-goodies.jp/archives/51019710.html
require 'jsonparser'
#require 'open-uri'
require 'net/http'
class BuzzurlBookmarkCounter
   def count urls
         api = "/api/counter/v1/json?url="
	 urls.each_with_index{|url, i|
	    api = api + "&url=" unless i == 0
	    api = api + url
	 }	
	 api = api.gsub(/\#/,'%23') 
	 src = ''
	 Net::HTTP.version_1_2
	 Net::HTTP.start('api.buzzurl.jp', 80) {|http|
	   response = http.get(api)
	   src = response.body
	 }
#	 open(api) do |file|
#	   src = file.read
#	 end 
	 parser = JsonParser.new
	 json = parser.parse(src)
	 result = Hash.new
	 json.each do |item|
	    result.store("#{item['url']}", "#{item['users']}".to_i)
	 end
	 urls.each do |item|
	    result.store(item, 0) unless ( result.key?(item) )
	 end
	 return result
   end
end
if __FILE__ == $0
   if ARGV.size != 1
      print "usage: #{__FILE__} <urls>\n"
      exit
   else
      result = BuzzurlBookmarkCounter.new.count(*ARGV)
      result.each do |url, count|
         puts "#{url} #{count}"
      end
   end
end

del.icio.us 用は以下.

#!/usr/bin/ruby
#http://webos-goodies.jp/archives/51019710.html
require 'jsonparser'
#require 'open-uri'
require 'net/http'
require 'kconv'
class DeliciousBookmarkCounter
   def count urls
         api = "/feeds/json/url/blogbadge?url="
	 urls.each_with_index{|url, i|
	    api = api + "&url=" unless i == 0
	    api = api + url
	 }	
	 api = api.gsub(/\#/,'%23') 
	 src = ''
	 Net::HTTP.version_1_2
	 Net::HTTP.start('badges.del.icio.us', 80) {|http|
	   response = http.get(api)
	   src = response.body
	 }
#	 api = "http://badges.del.icio.us" + api
#	 open(api) do |file|
#	   src = file.read
#	 end 
#	 src = src.toeuc
	 src = src.tojis
	 parser = JsonParser.new
	 begin
	   json = parser.parse(src)
	 rescue Exception => e
#          return e.backtrace
	   result = {"" => 0}
	   return result
	 end
	 result = Hash.new
	 json.each do |item|
	    result.store("#{item['url']}", "#{item['total_posts']}".to_i)
	 end
	 urls.each do |item|
	    result.store(item, 0) unless ( result.key?(item) )
	 end
	 return result
   end
end
if __FILE__ == $0
   if ARGV.size != 1
      print "usage: #{__FILE__} <urls>\n"
      exit
   else
      result = DeliciousBookmarkCounter.new.count(*ARGV)
      result.each do |url, count|
         puts "#{url} #{count}"
      end
   end
end

URL を引数に取ればコマンドラインから使えるし,以下のような検証用スクリプトも多分使えると思う (はてなlivedoor 用のコードも入ったままですが).

!#/usr/bin/ruby
require 'hatena_bookmark_counter'
require 'livedoor_clip_counter'
require 'delicious_bookmark_counter'
require 'buzzurl_bookmark_counter'
pml = "http://nao.s164.xrea.com/td/2007-04-19.html"
url = [pml,"#{pml}#p01","#{pml}#p02" ]
total = 0
total2 = 0
total3 = 0
total4 = 0
result = HatenaBookmarkCounter.new.count(url)
result2 = LivedoorClipCounter.new.count(url)
result3 = DeliciousBookmarkCounter.new.count(url)
result4 = BuzzurlBookmarkCounter.new.count(url)
puts "-- hatena\n"
puts result
result.each do |url, count|
   total += count
end
puts total
puts "-- livedoor\n"
puts result2
result2.each do |url, count2|
   total2 += count2
end
puts total2
puts "-- del.icio.us\n"
puts result3
result3.each do |url, count3|
   total3 += count3
end
puts total3
puts "-- buzzurl\n"
puts result4
result4.each do |url, count4|
   total4 += count4
end
puts total4

ちなみに Ruby の勉強は遅々として進んでないので,コードとしてはダメダメなはずです.すいません.



なんで open-uri じゃなくて NET:HTTP でやっているかというと,del.icio.us の場合になぜかうまく動かなかったから.謎.buzzurl のほうは open-uri でいけると思う.

あと,3 日間くらいハマッたのが,del.icio.usJSON フィードにマルチバイト文字が含まれてる場合に,JSON parser が Syntax Error を投げてくる件.UTF-8 なフィードしか扱わないはずなのに,なぜかフィードを JIS にしたら解決してしまった.激しく謎.しかも再現性がどうもあやしく,EUC にして解決したこともあった.なので,とりあえず例外が来たらダミーを返すようにしてあります.

上記 2 件の謎は,単独コードでテストしたときには発生しないので,tDiary の何かと干渉してたりするのかも知れない.

あと,SBS 側のサービスが死んでた時のために,ほんとは Timeout::Error をちゃんと拾ってあげるべきなんだろうね.さぼってるけど.



さて,おかげでトップページが随分重くなってしまって,たまにコンテンツ生成に失敗するようになってしまったので,個別記事へのアクセス時にのみ,ブックマーク件数を表示させるようにした.単に tDiary の comment_new から comment_description に移しただけだが (使い方間違ってる),だいぶ軽くなったとは思います.



どんな感じになったのかは,とりあえずうちの唯一のホッテントリ [2007-04-19] でも眺めてみて下さいw