Blogplot - Ming/Ruby で Flash形式のグラフをいろいろ作る

最終更新日: 2004-09-18 (公開日: 2004-09-18)


宮川達彦伊藤直也『Blog Hacks - プロが教えるテクニック & ツール100選』 に寄稿した記事の元の原稿です。


要約: mingplot というツールを使って Flash 形式のグラフをいろいろ作ってみます。

インターネット上には興味深いさまざまなデータが転がってい ます。Google で自分の名前を検索してみたり、思いつ いた駄洒落のヒット件数を調べて既出かどうかを調べたりしたこと がある人は多いと思います。本ハックでは、ネット上で得られるこう したデータをグラフ化するツール mingplot を紹介するとともに、 ブログへの応用を試みます。

mingplot とは

mingplot ming というラ イブラリを用いて Flash 形式のグラフを生成するツールです。 Googleのヒット件数をグラフ化するツール googleplot と、 Amazon の売り上げランクと価格をグラフ化するツール amazonplot が付属しています。

PNG などのビットマップ形式でグラフを生成するツールはたくさんありますが、 mingplot では Flash 形式を採用しています。 Flash 形式で生成する利点は、

といったところにあると思います。

下の画面は「バッ ドノウハウ」という言葉のヒット件数の推移をgoogleplot で グラフ化したものです。2004年3月になって突然ヒット件数が増え ていますが、これは、結城浩さんの「バッドノウ ハウからグッドラッパーへ」という文書を発端として多くの ブログで「バッドノウハウ」が話題にのぼったことによります。グラ フ化によってトレンドの動きが明らかになった例といえるでしょう。


「バッドノウハウ」のヒット件数の推移

mingplot の使い方

mingplot を使うにはまず以下のソフトウェアがインストールする必要があります。

筆者は Red Linux 9 上で動作確認を行っていますが、これらは Windows の Cygwin 上でも利用可能という情報があり ます。ming をビルドする時に make && make install ではなく make static && make install-static と実行するのが味噌のよう です。

また、原稿執筆時点ではming の最新版であるバージョン 0.3beta1 のビルドは autoconf, automake, libtool といったツー ルを要するため、筆者はビルドが簡単に行える 0.2a を用いました。

それではさっそく mingplot を使ってみましょう。 ここでは mingplot に付属している amazonplot を用いて amazon の売り上げランクと価格の推移をグラフ化する方法を紹介します。

amazonplot はデータの収集に Amazon Webサービス を利用するため、 実行には Amazon Webサービスのトークンが必要です。

4873111749 という ASIN (アマゾンでの商品番号、書籍なら ISBN) を持つ商品の売り上げランクと価格を調べて survey というディレクトリ以下にグラフを生成するには次のように実行します。(AMAZONTOKENの部分には自分のトークンを入れます)

% amazonplot --token=AMAZONTOKEN -o survey 4873111749

実行が成功すると、index.html, 4873111749*******.swf のようなファイルが作成されているはずです。この index.html をブラウザで表示すれば、Flash 形式のグラフが表示されるはずです。

次のように複数の ASIN を指定すると、それぞれの商品についてデータを収集して、個々のグラフを生成できます。

% amazonplot -o survey 4873111749 4274064379 4047913499

ASIN を 1行に 1つづつ記述したテキストファイル を -f オプションで指定して利用することもできます。

% amazonplot -o survey -f asin.txt

asin.txt: の内容:

4873111749
4274064379
4047913499

グラフの更新

グラフを更新するには、すでにグラフが存在するディレクトリを --update オプションで指定して次のように実行します。

% amazonplot --update survey 

amazonplot を、次のように -d オプションを指定して起動すると、 サーバとして常駐して 24時間ごとに自動的にグラフを更新するこ とができます。このとき、-f オプションで指定したキーワードの リストのファイルはグラフ更新の直前に再読み込みされます。

% amazonplot -d -o survey -f asin.txt

あるいは Unix の cron という機能を利用して毎朝 5時に更新する場合は次の ように crontab で設定します。

    00 05 * * * amazonplot -q -o survey -f asin.txt

ブログへの応用

mingplot を応用して tDiary のログをグラフ化する tdiarychart (高井直人氏作) というツールがあります。

tdiarychart は tDiary へのアクセス数だけでなくコメント数やリファラ─数もグラフ化してくれる凝ったツールですが、グラフがごちゃごちゃしがちなので、筆者は簡略版の tdiaryplot を作って利用しています。


tdiaryplot を利用した図

tdiaryplotのソースコード:

require 'mingchart'

def read_file (file_name)
  data = []
  File.open(file_name) {|f|
    f.readlines.map {|line| 
      if m = /^(\d\d\d\d-\d\d-\d\d) : (\d+),(\d+),(\d+)$/.match(line)
        time = Time.parse(m[1]).to_i
        total = m[2].to_i
        today = m[3].to_i
        data.push([time, today, total])
      end
    }
  }
  return data
end

if ARGV.length != 3
  puts "Usage: tdiaryplot FONT-FILE LOG-FILE FLASH-FILE"
  exit(1)
end

font_file_name = ARGV.shift
counter_log_file_name = ARGV.shift
flash_file_name = ARGV.shift

data = read_file(counter_log_file_name)
flash_file_name = flash_file_name
chart = MingChart.new(:flash_font => font_file_name,
                      :x_time_scale => true,
                      :drawing_methods => [:draw_dotted_line,
                        :draw_dotted_filled_line],
                      :y_axes => [:left, :right],
                      :right_y_label => "total count",
                      :left_y_label => "daily count",
                      :font_size => 42,
                      :x_time_scale_format => "%m/%d",
                      :line_titles => ["daily count", "total count"]
                      )
(data.first.length - 1).times {|i|
  chart.add_data(data, i + 1)
}
chart.draw
chart.save(flash_file_name)

tdiaryplot は tDiary の counter.rb プラグインのログファイル counter.log を元にグラフの作成を行います。 EfontSerif.fdb (mingplot に含まれています) というフォントを利用して tdiaryplot.swf というグラフを作成するには、次のように実行します。

% tdiaryplot EfontSerifB.fdb tdiary/cache/counter/counter.log tdiaryplot.swf

tDiary にこのグラフを貼るには

<object
 classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"
 id='tdiaryplot'
 width='250' height='180'>
 <param name='movie' value='tdiaryplot.swf' />
 <param name='quality' value='high' />
 <param name='play' value='true' />
 <param name='menu' value='true' />
 <param name='loop' value='false' />
 <embed name="tdiaryplot" src="tdiaryplot.swf"
           width="250" height="180"
           pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
           type="application/x-shockwave-flash">
 </embed>
</object>

のようなタグを tDiary のフッタに挿入すれば OK です。 グラフを毎日更新するには cron などに設定を入れます。

Hacking the Hack

さて、mingplot は日付と数値のペアのデータがあればなんでもグラフ化できます。 ここでは bulkfeeds の検索機能を利用して ヒット件数の推移をグラフ化する bulkplot を作ってみます。

bulkfeeds で miyagawa というキーワードを検索するには次のよう な URL にアクセスして検索結果を XML で取得します。

http://bulkfeeds.net/app/search2.rdf?q=miyagawa

得られる XML を見ると、ヒット件数が記録された

<bulkfeeds:total>77</bulkfeeds:total>

のような行が見つかります。この行を grep してヒット件数を抜き 出してもいいのですが、せっかくなので Ruby 1.8 以降に標準で備 わっている REXML ライブラリを使って XML として処理してみます。

require 'mingchart'
require 'cgi'
require 'net/http'
require 'rexml/document'

def get_hit_count (keyword)
  response = nil
  Net::HTTP.start("bulkfeeds.net", 80) {|http|
    query = CGI.escape(keyword)
    format = 
      path = sprintf("/app/search2.rdf?q=%s", query)
    response = http.get2(path)
  }

  doc = REXML::Document.new(response.body)
  count = doc.elements.to_a("rdf:RDF/channel/bulkfeeds:total").first.text
  return count.to_i
end

def draw (data)
  chart = MingChart.new(:flash_font => "EfontSerifB.fdb",
                        :x_time_scale => true,
                        :font_size => 42,
                        :x_time_scale_format => "%m/%d"
                        )
  chart.add_data(data)
  chart.draw
  chart.save("bulkplot.swf")
end

def main
  puts "Usage: bulkplot KEYWORD" if ARGV.length != 1
  keyword = ARGV.shift
  count = get_hit_count(keyword)
  File.open("bulkplot.dat", "a") {|f|
    f.printf("%d %d\n", Time.now.to_i, count)
  }
  data = File.new("bulkplot.dat").readlines.map {|line| 
    line.split.map {|x| x.to_i }
  }
  draw(data)
end

main

一番上の get_hit_count というメソッドにキーワードを渡すと、 ヒット件数が得られます。 残りのコードでは、ヒット件数の推移を適当なフォーマットでファイルに保存 して、グラフを生成を行います。 あとは毎日これを実行するだけです。

グラフ化してみるとおもしろそうなデータを見かけたら、 ぜひえいやっとハックしてみてください。


Satoru Takabayashi