‘Flickr’ タグのついている投稿

GoogleEarth上でFlickrの位置情報付き写真を見れるサービスを作った

2008 年 5 月 8 日 木曜日

blogを書けなくて(MTが再構築できなくて)もう1ヶ月ぐらい前に作ったものになるけど、春休みにRuby on Railsのお勉強をしていて、その最終成果物としてGoogleEarth上でFlickrのGeoTag付き写真を見れるサービスを作ったのでまとめておく。

ついでに、緯度経度でFlickrの写真を検索できるAPIも公開してある。

screen-capture.png

■実装方法

1.Flickrのタグ検索で、geotagが付いている写真を定期的にクロールしてきて、写真のURL、緯度経度をRailsのDBに溜める(photo modelに溜める)

2.GETパラメータで緯度経度をRailsに渡して、photo modelを検索する

3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る

4.GoogleEarthで視点が変わる毎にサーバーに問い合わせて、返ってきたkmlを表示するkmlを作る

5.mongrelでRailsを動かして、apache2のmod_proxy_balancerでRailsのURLをサブディレクトリに見せかける

こんな感じで。一番時間がかかったのが1のクローラの実装で、これは俺がRuby初心者すぎて2日ぐらいかかった。あとは、デンマーク行きの飛行機と帰りの空港からのバスでやったので5時間ぐらい。この辺は、データを溜めて、クライアントからのリクエストに基づいてフォーマットを決めて吐き出す部分が最初からできてるRailsのおかげ。

■1.geotag付き写真クローラ

まずFlickrはタグ検索ができるけど、数値じゃなくて「〜〜を含む文字列」としてしか検索できないので、例えば「北緯35度東経135度周辺の写真が欲しい」という時は使えない。なので、あらかじめメタデータを集めておいて、数値として範囲を指定して検索できるようにしておく。

geotagは小数点ありの値(geo:lat=35.2341など)なんだけど、普通にgeo:latやgeo:lonを含む写真一覧をFlickr APIから検索しても小数点無しのタグしか手に入らない。

小数点ありのタグを手に入れるために、Net::FlickrでFlickrAPIからタグ検索して、

Net::Flickrで全public photoからタグ検索 - shokaiの日記

“geotagged”タグを含む写真をリストアップして、それから再度photo_idを使ってFlickrAPIのphotos.getInfoメソッドを使ってtagのraw attributeを見なければならなかった。

s.h.log » RubyでFlickr APIのphotos.getInfoを呼ぶ

クローラ自体はRailsで実装されていなくて、ActiveRecordだけを使ってcronで1時間毎に実行されている。

s.h.log » RailsなしでActiveRecordだけ使って、SQLiteを読み書きする

SQLiteのファイルがRailsと共有されているだけ。今回は、Rails側からの書き込みが無いので特に問題は起こらないだろうと判断した。

いまのところ10万枚の写真が集まった。SQLiteのファイルが欲しい人はあげます。

あと、クローラは連続でHTTPアクセスするとFlickrに悪い気がするので、適当にsleepを入れてみてるんだけど、そうすると実行に結構時間がかかる。これが、クローラを作って動かして直して作って…と繰り返す時に面倒だったが、和田さんに言われてscreenをデタッチ/アタッチするという技を覚えた。デタッチしておくと、sshを切断してもクローラが止まらなくて、アタッチしたら普通に続きからできる(もしくは結果が出てる)screenはクローラ作ってるときに重要。

■2.緯度経度をGETパラメータでRailsに渡して検索する

photos.kml?lat=35&lon=135&size=thumb

みたいな形式で、パラメータを渡してDBに溜めた写真を検索する。

KMLを全部出すと多すぎたので、緯度経度を指定してその周囲の写真だけ出す - shokaiの日記

paramsで受け取れる。パラメータ名はシンボルになっているので注意。

controllerで、ActiveRecord::Baseのfind_by_sqlメソッドで普通に検索。(この方法だと四角い。PostgreSQLやMySQLの空間型を使えば丸くできるらしいがとりあえずSQLiteでやる)

そしてmodelの配列をViewに渡してやる。

■3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る

kml形式のviewを作る。views/photos/index.html.erb を参考にして、index.kml.erbを作ればok

mime-typeにkmlを追加しておく必要があった。

flickrのgeotagついてる写真を収集してたので、kml出力するようにした - shokaiの日記

結果は巨大なkmlになるので、Rails標準搭載のWEBrickだときつい。でかいときはhttpサーバーをmongrelに換える。

MongrelでRailsをデプロイ - shokaiの日記

apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする - shokaiの日記

■4.GoogleEarthで移動する毎に検索するkmlを作る

GoogleEarthの表示を作っているkmlは、静的な表示だけでなく、NetworkLinkタグで別のKMLの内容をURLを指定して読み込める。さらにViewRefleshModeをonStopにすると、画面の移動が止まった時に再読み込みできる。

再読込時に、視点の緯度経度を[lookatLat][lookatLon]で取得できるので、

lat=[lookatLat]&lon=[lookatLon]

としてNetworkLinkで読み込むkmlのURLの後ろにくっつけてやる事で、GETパラメータになる。

GoogleEarthで表示している場所の緯度経度から検索する - shokaiの日記

■5.mongrelでRailsを動かして、apache2のサブディレクトリに見えるようにする

デプロイ。

4まではMac OSX上でやって、ここからは大学院棟に置いたUbuntuに移し替えた。RailsをSQLite+Mongrel環境で動かして、URLをapacheで隠すようにすると、Railsプロジェクトのディレクトリをそのまま移し替えるだけでほぼ動くので超楽。

Flickrのgeotag写真を検索する - shokaiの日記

apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする - shokaiの日記

MongrelでRailsをデプロイ - shokaiの日記

Mongrel入れる - shokaiの日記

———–

こんな感じで、クローラの実装と、バックエンドのサービスとしてAPIを吐くためのRails、というのを覚えた。

今まで戦略的に「長い時間をかけたインタラクション」をするモノや、「データを共有した複数のモノと人とのインタラクション」を作る事を避けていたんだけど(ややこしくてプロトタイピングできないものは作らない方針なので)

Rails使うとサクサクとこのぐらいまではいけるようになったので、自分の得意なフィジカルなデバイス作成と合体させて何か新しい物を作る予定。

RubyでFlickr APIのphotos.getInfoを呼ぶ

2008 年 3 月 17 日 月曜日

Net::Flickrをインストールしたら、flickr.photos.getInfoメソッドが実装されてなかったので良い機会なので実装してみた。

flickr apiをrubyで使う - replore的日記がとても参考になった。

FlickrAPIは普通にRESTなので、REXMLで取得してparseする。

今回自分で実装したのはgeotagまわりのため。FlickrのAPIの仕様でtagは小数点やハイフンが消されるので、その元の値を取るのにgetInfoメソッドが必要になる。Tagオブジェクトのrawからアクセスできるようにした。

使い方はphoto_idをコンストラクタに渡す。

info = PhotoInfo.new(photo_id)

info.tags.each{ |tag|

  puts tag.raw

}

flickr-photos-getInfo.rb

require ’open-uri’

require ’rexml/document’

require ’cgi’

FLICKR_API_KEY = ’your-api-key’

def flickr_call(method_name, arg_map={}.freeze)

  args = arg_map.collect {|k,v| CGI.escape(k) << '=' << CGI.escape(v)}.join('&')

  url = ”http://www.flickr.com/services/rest/?api_key=%s&method=%s&%s” %

    [FLICKR_API_KEY, method_name, args]

  doc = REXML::Document.new(open(url).read)

end

class PhotoInfo

  @xml_doc

  def initialize(photo_id)

    @xml_doc = flickr_call(’flickr.photos.getInfo’, ’photo_id’ => photo_id)

  end

  def tags

    tag_list = Array.new

    REXML::XPath.each(@xml_doc, ’//tag’){ |tag|

      tag_list << Tag.new(

                          ’id’ => REXML::XPath.first(tag,’attribute::id’),

                          ’author’ => REXML::XPath.first(tag,’attribute::author’),

                          ’raw’ => REXML::XPath.first(tag,’attribute::raw’),

                          ’tag’ => tag.text

                          )

    }

    return tag_list

  end

end

class Tag

  def initialize(args)

    @id = args['id']

    @author = args['author']

    @raw = args['raw']

    @tag = args['tag']

  end

  

  def id

    @id

  end

  

  def author

    @author.to_s

  end

  

  def raw

    @raw.to_s

  end

  

  def tag

    @tag.to_s

  end

  

  def is_machine

    if @tag =~ /.+:.+=.+/

      return true

    else

      return false

    end

  end

  

  def is_geo

    if @tag =~ /geo:.+=.+/

      return true

    else

      return false

    end

    

  end

end

C# - Flickr.NETでFlickrアップローダ

2008 年 1 月 14 日 月曜日

前の記事に続き、Flickr.NETを使う。

今度はFlickr Uploaderを作ってみた。Flickr.NETには

・Flickr APIへの認証(read/write/delete権限の取得)

・ファイル名を指定してアップロード

などの機能が揃っているのでさくっと作れた。

できたもの => Archive

ドラッグアンドドロップした写真1枚をアップロードする

uploader

tagやtitleなどが適当に付いている

using Flickr.NET

■oAuthでの認証のためのtoken発行

今回はAPI keyに加えて、secretも使ってfrobを作ってtokenの発行を行わないといけない。

まずkeyとsecretを取りに行く→Flickr Services

その辺の仕組みは1つ前の記事と、

Flickr API の認証 - まちゅダイアリー (2005-11-01)

s.h.log: Flickr::Uploadで写真をアップロード

を参考に。

■プログラムを書く

まずfrobを作る。あとで使うのでとっておく(2回作ると違う値ができてしまうので)

Flickr flickr = new Flickr();

flickr.ApiKey = “your-api-key”;

flickr.ApiSecret = “your-api-secret”;

String flickr_frob = flickr.AuthGetFrob(); // frobの作成

で、認証画面をwebブラウザで開いて「OK」ボタンを押してもらう

System.Diagnostics.Process.Start(flickr.AuthCalcUrl(flickr_frob, AuthLevel.Write)); // 認証画面をブラウザで開く

OK押してもらってから、さっき作ったfrobを使ってtokenを取りに行く。

try{

Auth auth = flickr.AuthGetToken(flickr_frob);

flickr.AuthToken = auth.Token; // token取得

}

catch (FlickrApiException ex)

{

Console.WriteLine(ex.Message);

}

無事tokenを取って、Flickrオブジェクトにセットできたら、ファイル名を指定すればアップロードできる。tagやtitleやdescriptionを適当に付けてみた。

Photo p = new Photo();

p.PhotoId = flickr.UploadPicture(”PhotoFileName”, “test photo”, “これはてすとです”, “test,uploadertest”);

p.UserId = auth.User.UserId;

System.Diagnostics.Process.Start(p.WebUrl);

uploadされた写真のphotoIdが返ってくるので、それを使ってWeb上でのURLを求めることも出来る。今回はまたブラウザで開いてみた。

UploadPictureメソッドはどうやら内部でThread.Sleep()を呼んでいるみたいなので、そのままThreadで実行すればマルチスレッド化できる。

uploadを途中で止めるメソッドが無いみたいだけど、途中で止めたい時はスレッドで実行してAbort()してしまえば止まった。

詳しくは今回作ったアプリのソース参照

(続きを読む…)

C# - Flickr.NETでtag検索

2008 年 1 月 14 日 月曜日

Flickr.NETという.NET Framework用のライブラリを使って、Flickr APIからタグ検索してみた。2年ぐらい前に使った時より、dllのファイルサイズが1.5倍に増えててた。

できたもの => Archive

using Flickr.NET

■dllを手に入れる

FlickrNet API Library - Home

[Release]から2.1.5をダウンロードしてきた。

んで、[参照の追加]でリンクして、

using FlickrNet;

する。

■API keyを手に入れる

Flickr ServicesからAPI keyを手に入れないといけない。メールアドレスを登録してすぐ発行してもらえる。

今回は「デスクトップアプリ用」を選択。

(検索だけなら、secretとtokenを使ってoAuthで認証する必要は無い)

■プログラムを書く

Flickr APIのラッパーなので、基本的な仕様はFlickr APIの方を見た方が良い。

今回はflickr.photos.searchを叩いてみた。

まずFlickrというクラスが全ての根になっている

using FlickrNet;

Flickr flickr = new Flickr(”your-api-key”);

flickr.photos.searchでは色々なパラメータを渡すが、Flickr.NETではPhotoSearchOptionsクラスで集約されている。今回はタグだけでeveryoneから検索するのでこれだけだけど、もっと色々パラメータが指定できる。

PhotoSearchOptions opt = new PhotoSearchOptions();

opt.Tags = “food, sfc”;

opt.TagMode = TagMode.AllTags;

Photos photos = flickr.PhotosSearch(opt); // 検索

Photosクラスで返ってきた結果からURLを取り出して、表示する。

PictureBox.Imageにストリームから読み込ませるための関数 DownloadPicture(”URL”) を利用してダウンロードする。

Photo p = photos.PhotoCollection[0]; // 1枚目

pictureBox.Image = Image.FromStream(flickr.DownloadPicture(p.MediumUrl));

textBoxPhotoUri.Text = p.WebUrl;

(続きを読む…)