--- layout: old_post title: Six ApartのRelationship Update Streamをグラフ描画してみた permalink: /tatsuya/show/402-six-apart-relationship-update-stream ---
mixiエンジニアブログで知ったのですが、Six ApartがWebサービスのソーシャルデータ共有のために Relationship Update Stream という実験を始めたそうですね。
詳細は先ほどのSix Apart公式サイトやmixiエンジニアブログを見て頂くとして、ざっくり言うと「ソーシャルな情報を扱うWebサービスで、人と人の関係に変化が合った場合(フレンドになった等)Six Apartへ通知、溜まったデータは自由に共有・利用できる」という物らしい。データ取得はGETで http://updates.elsewhere.im/atom-stream.xml へアクセス、データ更新はOAuthで認証した後AtomFeedをPUTするだけとシンプル。
手始めにGraphvizでグラフ描画してみました。
以下、手順メモ
まずGETでデータ取得、GETリクエストするとデータがストリームで流れ続けるというのが面白い。でもちょっと試すには使いづらいのでファイルに落とした
wget http://updates.elsewhere.im/atom-stream.xml
試しに10分くらい落としてみた。あとは普通にファイルなので下記のようなRubyスクリプトで解析、一応ストリームを意識してREXML::Parsers::StreamParserで解析してみた(HTTPでストリーム的にデータを読み込む、とかRubyでどうやるの?TCPSocket使って実装するのかな)
require 'rexml/parsers/streamparser' require 'rexml/parsers/baseparser' require 'rexml/streamlistener' class RUSListener include REXML::StreamListener attr_accessor :relation, :name_map def initialize @relation = {} @name_map = {} @current = [] end def tag_start(name, attributes) if name=="link" && attributes["rel"]=="related" @current << attributes["href"] @name_map[attributes["href"]] = attributes["title"] unless @name_map[attributes["href"]] end end def tag_end(name) if name=="entry" unless @relation[@current[1]] @relation[@current[1]] = [@current[0]] else @relation[@current[1]] << @current[0] end @current = [] end end end File.open("./rel_test.dot","w") do |file| source = File.read "./atom-stream.xml" listener = RUSListener.new REXML::Parsers::StreamParser.new(source, listener).parse outputter = [] listener.relation.each do |key, value| value.each do |from| if listener.relation[from] && listener.relation[from].size > 1 outputter << "\"#{listener.name_map[from]}\" -> \"#{listener.name_map[key]}\";\n" end end end file.write("digraph Relation {\n #{outputter.join} }\n") end
参考にした > http://www.nslabs.jp/ruby-rexml.rhtml
あと、データが短期的すぎてネットワークに集約しないので、ある程度フィルタリングした。
Graphvizで出力
dot -Tpng rel_test.dot -o rel_test.png
出力結果がこれ(見やすく切り取っています)
むむ、やっぱある程度データの量貯めないと面白くないな。一週間くらい溜め込んで試してみたい。
ー以下余談ー
というか fooo.name でこんな情報の収集を早くすれば良いって話か。でもSNSなんかのフレンド情報を fooo.name でストアするのは問題あるよな、とも最近思ってきた
・「リンク情報を保存してる」と言い張る
・文句がついたら、そのサイト情報は保存しないようブロックして対応する
で逃げられないかな?
twitter繋がり = //a[@rel="contact"]
del.icio.us繋がり = //li[@class="netuni"]/a[@class="uname"] ( http://del.icio.us/network/xxx のページで)
みたいにXPathでフレンドURLをサイト毎に定義してスクレイピングする。ってのが良いかな、と思うんだけどな。
いちいち有象無象のフレンド情報取得APIを叩くのはめんどくさい、サービス毎に実装すんのかよみたいな