--- 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でグラフ描画してみました。

rel_test

以下、手順メモ
まず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

出力結果がこれ(見やすく切り取っています)

rel_test

むむ、やっぱある程度データの量貯めないと面白くないな。一週間くらい溜め込んで試してみたい。

ー以下余談ー

というか 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を叩くのはめんどくさい、サービス毎に実装すんのかよみたいな