アーカイブ
Flickrダウンローダを作った
Rubyで。ダウンロード部分はwgetに投げているのでUnix系でしか動かせないかもしれない。REXML::XPath使うのの勉強になった。
shokai / Flickr downloader / overview — bitbucket.org
タグ検索してユーザ指定したりもして(権限があれば)オリジナル画像を一括ダウンロードできる。
実行例
flickr-download beer,food 51753258@N00
で俺がbeerとfoodをタグを付けた写真が全部取ってこれて空腹を紛らわせれる。51753258@N00のところはユーザIDで、各ユーザぺージのRSSのURLを見ればわかる。
オリジナル画像を手に入れるためにFlickr APIのphotos.searchとphotos.getInfoのラッパーを実装した
Flickrのcontactの写真をMediumサイズで全部見る
Pipes: Flickr Auto Feedで新着500件のRSSを作ってGoogle Readerに読み込ませたら快適になった。サムネイルじゃないのでビデオもGoogle Reader内で見れる。
ステキなガジェットを作っている人をかたっぱしからFlickrのコンタクトに加えていたら、いつのまにか100人を超えていて、とんでもない量の新着写真が毎日来るようになった。
たとえば今、2日ぶりに新着を見てみたら656枚の写真があった。
Flickr: From your Contactsを見ると自分のコンタクトのアップロードした写真の一覧があるが、サムネイルなので何がなんだかわからなくて全然駄目。
RSSも出ているけどこれもthumbサイズだし、なぜか新着20件しか取得できないので使い物にならない。普通のFlickrユーザは数十枚まとめてアップロードするので、すぐに新着が流れてしまって取りこぼしてしまう。
本当はこのpipesをLDRで読みたいけど、PipesのRSSをLDRに登録してもPipes自体が重いからなのかFeedが来ない。なのでこれだけはGoogle Readerを使う事にした
—–追記—–
Google Reader Minimalistic for Greasemonkeyを使うと写真が画面に入りきるようになる
GoogleEarth上でFlickrの位置情報付き写真を見れるサービスを作った
blogを書けなくて(MTが再構築できなくて)もう1ヶ月ぐらい前に作ったものになるけど、春休みにRuby on Railsのお勉強をしていて、その最終成果物としてGoogleEarth上でFlickrのGeoTag付き写真を見れるサービスを作ったのでまとめておく。
ついでに、緯度経度でFlickrの写真を検索できるAPIも公開してある。
■実装方法
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を呼ぶ
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’
defflickr_call(method_name,arg_map={}.freeze)
args=arg_map.collect{|k,v|CGI.escape(k)<<'='<
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)
endclassPhotoInfo
@xml_doc
definitialize(photo_id)
@xml_doc=flickr_call(‘flickr.photos.getInfo’,'photo_id’=>photo_id)
end
deftags
tag_list=Array.new
REXML::XPath.each(@xml_doc,’//tag’){|tag|
tag_list<
‘id’=>REXML::XPath.first(tag,’attribute::id’),
‘author’=>REXML::XPath.first(tag,’attribute::author’),
‘raw’=>REXML::XPath.first(tag,’attribute::raw’),
‘tag’=>tag.text
)
}
returntag_list
end
endclassTag
definitialize(args)
@id=args['id']
@author=args['author']
@raw=args['raw']
@tag=args['tag']
end
defid
@id
end
defauthor
@author.to_s
end
defraw
@raw.to_s
end
deftag
@tag.to_s
end
defis_machine
if@tag=~/.+:.+=.+/
returntrue
else
returnfalse
end
end
defis_geo
if@tag=~/geo:.+=.+/
returntrue
else
returnfalse
end
end
end
C# – Flickr.NETでFlickrアップローダ
前の記事に続き、Flickr.NETを使う。
今度はFlickr Uploaderを作ってみた。Flickr.NETには
・Flickr APIへの認証(read/write/delete権限の取得)
・ファイル名を指定してアップロード
などの機能が揃っているのでさくっと作れた。
できたもの => Archive
ドラッグアンドドロップした写真1枚をアップロードする

■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()してしまえば止まった。
詳しくは今回作ったアプリのソース参照



最近のコメント