Six ApartのRelationship Update Streamをグラフ描画してみた

26 Oct 2007

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

fooo.name更新 - バグ潰しとtako3.com互換API

15 Oct 2007

fooo.name 幾つかバグ潰しと、API更新 しました。

主な変更点はtako3.com互換APIの追加です。詳細な情報はこちらをどうぞご確認ください。
次はGreasemonkeyスクリプトでAPIの実験みたいなのをやろうかな。あと、今後のTODOをまとめ

TODO:
・同一アカウント&別人問題の対応

さすがに今のままだと、誤情報が混じってくるのである程度フィルタリングを設けたい。

A) 人と人の繋がりで判断。複数サービスで "tkmr" が同じ "hoge" さんをフレンドにしていれば、その複数サービスの "tkmr" は同一人物とみなす(一致率がある閾値を超えたら)

B) 各ページの特徴語をベイズフィルタに掛ける。自分だったら "tkmr", "ruby", "rails" なんかの頻出語、URL、フレンドのアカウント名等を複数ページで調べる。少なくともこれで海外サービス等の別人はフィルタリング(グルーピング)できるかも。(たとえば "tkmr" の場合は http://www.myspace.com/tkmr

あとベイズフィルタで閾値を設ければ、死にアカのフィルタもできるかも。作ったけど全く更新していないページ等はマッチしないので。というかB方式はA方式を内包するのか。

・フィルタリング選択
用途によって求められる精度も違うと思う。ゆるい用途ならフィルタも要らないし、ある程度ならベイズフィルタ、さらに信頼できる情報が必要なら「同一セッションで複数サービスの認証を通った証明」フィルタ、とか選択可能にしたい。http://fooo.name/accounts/tkmr?filter=high みたいな

・繋がり情報の収集
サイトのURLパターンはあるので、各ページにある "フレンドへのリンク" のURLをXPath等で設定可能にすれば収集できるかも。
twitter繋がり = //a[@rel="contact"]
みたいな。で http://twitter.com/[name] にマッチすればフレンドのアカウント名も取れるし。人と人の繋がりがHTMLでも提供されてれば汎用的に行けるかな。

URLの登録拒否サポート(ブロックリスト)
今は細々とやってるので良いかなと思うけど、今後を考えると「私のURLを登録しないで!」というサポートフォームみたいなのは付けた方が良いかな。ブロックリストみたいな。
でもどうやって本人を確認するか、認証APIがある & OpenIDなら認証を通ればOKとできるが。。

ソーシャルグラフ共有サイトと言うかなんと言うか、Fooo.name!!というWebサービスを作った

11 Oct 2007

(最後、少し追記しました)

最近、本業も暇になってきた & 連休続きだったので、ひとつWebサービスを作ってみました。

Picture 2 http://fooo.name/

で、どんな物なのか

と言うと、Web上で誰か気になる人を見つけたときに「その人が、他にどんなページを持ってるか?」という情報を探すことができます(運が良ければ)

具体的には、このブックマークレット 「Fooo.nameから探す」を使ってもらうのが判り易いと思います 何か適当なWebサイト上でこのブックマークレットを実行すると、そのサイトに関連するURLを探し表示します。

見つかった場合 : http://twitter.com/tkmrを検索 Picture 3

無事関連するURLが見つかった場合は、他のページを見て回るもよし。LivedoorReaderで「まとめて購読」するリンクを設けているので、男らしく全部まとめて購読するのも良いと思います。

残念、見つからなかった場合:http://twitter.com/hogeを検索 Picture 4

見つからなかった場合は、ぜひ本サイトへ情報を登録してやってください;)ついでにその人が使っているアカウント名等を合わせて登録して貰えると大感激です。 「大抵の人は複数のWebサービスで同じアカウント名を使う」「大抵のWebサービスはユーザ固有ページURLにアカウント名を使う」というゆる0い方針のもと。アカウント名が追加されると、自動で情報収集を試みます。

もちろんhogeさんの個人ブログは自動で登録されない or 別人のhogeさんが持っているページが登録される、等の問題もありますが、現状サイト内の情報はほぼすべて自由に編集できるので、wiki的に編集して補正して貰えると大感激です。

認証について
ですが一応OpenIDによるログイン認証を設けています。本来は「livedoor関連サービスはlivedoor OpenIDでログインした場合のみ編集可能」等とするのが正しいと思います、ですが現状あまりOpenIDが普及していない & できるだけ編集のハードルを上げたくない。ということで未ログインでもほぼ編集可能です。例外として http://twitter.com/[name] というサイト情報パターンの編集だけは認証を掛けています、少し影響が大きいので。

APIについて
とりあえず現状 HTML / XML / JSONP / RSS & Atom の形式で情報を取得できます。下記のように好きなページへ拡張子を付けることで、その拡張子に従った形式のデータを返します。

例:アカウント "tkmr" の情報 HTML - http://fooo.name/accounts/tkmr
  XML - http://fooo.name/accounts/tkmr.xml

例:http://twitter.com/tkmr で検索 HTML - http://fooo.name/accounts/search/http://twitter.com/tkmr
  JSONP - http://fooo.name/accounts/search/http://twitter.com/tkmr? format=json&callback=hogeCallback

JavaScriptならJSONPでお手軽に。RailsならActiveResourceでフルアクセス。詳細は下記のAPIページをどうぞご覧ください。 http://fooo.name/main/aboutapi

何が目的? & 何故作ったか

についてですが、単純に言うと「人と人の関係がAPIで取得できたら面白いんじゃないか」という思いがあります。「mixiの友達が3人以上購読したRSSは自動で購読」「Twitterのフレンドが一定数以上引用したURLを開く。一定数以上含まれたHotなキーワードをBlog検索して結果のRSSを購読・・・・」などなど、それがWebサービスを横断して色々できると面白いかなと常々思っていました。これは最近話題のソーシャルグラフというキーワードが上手く表現していると思います。(下記のページが判り易いと思います)

[翻訳] ソーシャルグラフについて

また少し話は逸れますが、下記のページにある SNS型RSSリーダー というアイデアを見つけたのもきっかけの一つです

なめらかなメッセージング- ised議事録 - 2.設計研第7回:鈴木健

上の記事によると、インターネットの登場には「マスメディアによるメディアの独占を崩壊させ、多様な個人が世界中の人々とコミュニケーションする」という夢があったが、現状達成されていないし、良い方向に向かっているとも思えない。なぜなら人間の認知力には限界があるので情報を上手くフィルタリングしないと下記の問題が発生する

1) マスメディア化   結局、普通の人が見るのは有名なページ or サイト。そのためインターネットが既存のマスメディアを破壊しても、第2, 3のマスメディア(Yahoo , Google , 一握りの有名サイトと無数の無名サイト)が発生する

2) たこつぼ化   自分の興味のある閉じられたコミュニティの情報にしか耳を傾けなくなる。(本屋に行くとき「本を買う」というのはもちろん、何か新しい分野の情報に出会う、ために本屋をぶらつくということがあるかと思います。逆に検索エンジン中心のWebは興味の無い情報に出会う確率が低い、そこで上手い配分で偶然性を入れる はてブやTumblrが流行っている?)

3) SPAM化   無理矢理外部から「たこつぼ」の中に情報をプッシュすると、本来有益な情報もSPAMになる。(livedoor Reader なんかはもっと多くの人に使ってほしい、と個人的に思っているけど、それを現状必要としていない人に伝えるのは至難の技だと思う。必要としてない情報は(実は有益でも)邪魔なSPAMになってしまう)

これらの問題を解消するために、人と人の繋がりを利用した「SNS型RSSリーダー」はどうか?というアイデアが面白いと思う。

ざっくり言うと「友達の読んでいるRSSが流れてくるRSSリーダ」のようです。詳細は上記ページを見て頂くとして、既に繋がりのある友達からの情報なら興味を持ち易いし「高校の友達フィード」から全然違う分野の情報が流れ込んでくれば、別分野に興味を持つ確率も高まる(SPAM化、たこつぼ化の解消)マスメディア化に関しては決定的な解消と行かないかもしれませんが、中心の無いネットワークが結びつくので比較的マスメディア化も分散するのではないか、という考察がされています。

アイデア自体は面白いと思うのですが、ここは 「ソーシャル情報によるRSSアグリゲート / UIとしてのRSSリーダ」と実装を分離することができると思います、そしてUIに関しては既存のRSSリーダを利用し、ソーリャル情報によるRSSアグリゲート機能も「ソーシャル情報のDB / RSSアグリゲータ」と分離するべきで、とりあえず「ソーシャル情報のDB」を実装してみよう、と思い試みた結果できたのが本サイトになります。

次の段階

ということで次の段階としては、人と人の繋がりの情報を収集する仕組みを実装しようと思います。 例えば「[翻訳] ソーシャルグラフについて」のページで言う "エッジ" の実装になるのかな、と考えています。

追記

少し追記を。
今回作成したFooo.nameと同じコンセプトのWebサービスに http://tako3.com/ というサービスがあります。
同じコンセプトのサービスがあるなら、車輪の再発明をする必要ないじゃん。とも思いましたが、tako3.comでは「量より質」の方針で集めているようで 、個人的に「質より量」で実装してみたかったのでやってみた次第です。
(というか、昨日作者の方のブログへコメント出しておきながら、言及を忘れてました。。申し訳ないです)
ということで tako3.com も合わせてどうぞ :-)

シェルスクリプトからFireFoxを操作するFresno

08 Sep 2007

via Tumblr

Fresno - SIMILE

MozReplでFireFoxをtelnet待ち受け状態して、シェルスクリプトから同じくtelnetで繋いで操作しちゃうらしい。
面白いこと考えるなー・・

fresno -p "http://yahoo.com"

-p でページを開いたり

fresno -c -j "alert('Hello world')"

-c -j で今見てるページに対して、JavaScriptを実行できる。

今見てるエロサイトの画像をダウンロードするのも

fresno -c -j "document.body.innerHTML" | grep img \
| ruby -Ke -e 'puts gets.scan /src="([^"]*)"/' | xargs wget

みたいにワンライナーでお手軽。フルパスじゃなかった場合、とか色々あるけど。

実用的かと言われるとそうでもないけど、面白い。

世界中のサイトを見尽くしたいけど限界は確かにあって、その限界に近づけられるなら何をしても良い

30 Aug 2007

昨日ふと思い出したんだけど、昔大学の先輩で自称WebデザイナーのHさんという人がいた。その人の作ったサイトを見ると一見カッコいいんだけど、よく見ると何かおかしい・・・それ、実はただのデカイ一枚の画像だった!サイト内の文章も全て。

あ・・・・ありのまま今起こ... - ポルナレフがありのまま起こったことを話す - Hatena Serif

一枚のjpgファイルを分割してテーブルで配置して、リンク張ってるだけ。これなら「ずれない」「文字キレイ」「レイアウト自由」と良い事だらけ、という主張だったと記憶してる。もちろん依頼者も知人・友人の範囲で収入も月数万円のレベル、両者Webの知識は限りなく0に近いのでこれで良かったんだろうし、Web草創期ののどかな話だったように思う。

それにしても、何故Hさんは「ページ全体を一枚の画像にすればずれない!」っていう天才的なアイデアを思いついたんだろう?多分DTPデザインとしては当然の「デザインは全ての環境で同じ表示であるべし」という感覚をサイトデザイン上で試行錯誤した末に出た結論なんだろうけど、それにしても信じられない

全てのブラウザで同じに見える必要はないし、それは不可能で間違ってる

この記事にもあるように、Webデザインは全ての環境で完璧に同じに見える必要は無いし、パソコンのみで完璧に美しく見えるより、携帯でもPSPでも音声リーダーでもなんでも "それなり" に見えるほうが重要。さらに言うと "自由" に見る事ができる方が重要だ、Greasemonkeyで自由にページへ機能追加/カスタマイズできることのほうが、文字/レイアウトをキレイに表示できることの1000倍は価値があると思う。そのためにはソースこそキレイである必要がある、本当の美しいWebデザインはソースから美しい、であって欲しい。

「ページ全体一枚の画像レイアウト」を見て当時は「い、良いんじゃないですか。個性的で。。」としか言えなかったけど、今なら無数にあるGreasemonkeyスクリプトを紹介して反論したい、ユーザの手で自由に機能追加されているLDRを紹介して、AutoPagerizeLDRizeで徹底的に自由に閲覧できるWebサイトを紹介したい。Tumblrのdashbordでピンを立て一気にReblogするLDRize_tumbler_dashboard_reblog.user.jsを見てもらいたい。このスクリプトたち本当に欲望に忠実で良い、ピン立てて一気にはてなへブックマークとか、ピン立てて一気にLDRへ購読とか。文字のサイズやレイアウトがずれることをガマンして、むしろソースをキレイにすれば、これだけ多くのメリットがあるのに。勿体ない。

実際試しにこのブログもAutoPagerizeに対応してみたけど、microformat対応なら作業は実に簡単、"次へ"のリンクに rel="next" を付けて、次ページを埋め込む位置/エントリ一覧全体のdivにclass(autopagerize_*******)を指定するだけ。5分で出来る。なのにこんなに便利で良いんだろうか?もし全世界のブログサービスがこのmicroformatsに対応したことを想像すると妄想が止まらない、AutoPagerizeで多くの無駄な時間が節約できる。もっといっぱいエロ画像収集ができる。

世界中のサイトを見尽くしたいけど限界は確かにあって、でもその限界に近づけられるなら多少文字やレイアウトがずれても良いと思う。