第1回では,マッシュアップの背景やWebサービスAPIにかかわる技術要素をご紹介しました。今回からはサンプル・コードを交えて,具体的なWebサービスAPIの使い方を紹介していきます。今回は,Flickr APIを利用した画像検索を取り上げます。サーバーサイドのプログラムが不要なように,ブラウザ内で動作が完結する JavaScript を利用します。キーワード指定で Flickr 上の画像を検索し,ブラウザ上にカンタンに表示できます。

図1:http://www.flickr.com/

 Flickr APIは, 米国Yahoo!が提供する写真共有サイト Flickr のコンテンツ(図1)に,プログラムからアクセスするためのAPIです。 Flickr は,無料コースでも200枚(月間20MB)まで画像(デジカメ写真等)を投稿できます。 画面上のメッセージ類はすべて英語ですが,日本国内の利用者数も多いサイトです。 Flickr はlivedoor PICSと操作性も近いです。

Flickr APIの利用準備

 Flickr APIには表1に示すように多くの機能があります。 写真のアップロードから,管理・コメント投稿など Flickr サイト上で利用できるほとんどすべての操作が API 経由でも実行可能になっています。 今回は写真の検索機能を利用します。

表1:Flickr APIの主な機能

flickr.auth認証
flickr.blogs外部ブログ投稿
flickr.contactscontact管理(お気に入りユーザー)
flickr.favoritesfavorites管理(お気に入り写真)
flickr.groupsgroups(グループ)管理
flickr.interestingness人気写真取得
flickr.peopleユーザー検索
flickr.photos写真管理・検索
flickr.photos.comments写真ごとのコメント管理
flickr.photos.geo写真ごとの緯度経度管理
flickr.photos.licenses写真ごとのライセンス管理
flickr.photos.notes写真ごとのノート管理
flickr.photos.transform写真の変換(回転処理)
flickr.photos.upload写真の投稿
flickr.photosetssetの管理(写真アルバム)
flickr.reflectionメソッド一覧・情報
flickr.tagsタグ管理
flickr.test動作テスト用
flickr.urlsURL仕様情報

 Flickr APIのインタフェースとしては, REST / XML-RPC / SOAP の3種類が用意されています。 通常は,実装が容易な REST を利用することが多いようです。 REST リクエスト時のレスポンス(APIから返却される結果データ)は, RSP 形式という独自の XML フォーマットで出力されます (Plain Old XML)。 XML以外にも,JSON形式(JavaScript Object Notation), JSONP形式(JSON with Padding), PHP serialize形式での出力も可能です。 今回は,JavaScriptから処理しやすいJSONPを利用することにします。

 Flickr APIの利用(ライセンス認証用API Keyの取得)には, 米国Yahoo!の会員登録が必要です。 英語のメッセージなので少し面倒ですが, [Sign Up] のボタンから会員登録を行ってください(日本のYahoo! JAPANのアカウントは利用できません)。 会員登録が完了したら,続けて API Key を取得します(図2)。32文字の英数字からなる文字列がAPI Keyです。 16文字の英数字secretは,パスワードのようなものですから,公開してはいけません。

図2:API Keyの取得

flickr.photos.searchメソッドによる画像検索

 画像検索ではFlickr APIの提供するメソッドの中から,flickr.photos.searchを利用します。 このflickr.photos.searchメソッドは,以下のパラメタ引数(表2)を指定できます(REST利用時のクエリー変数)。 Flickrのデータベースから,テキスト・投稿者・タグを指定して, 写真を検索することが可能です。

表2:flickr.photos.searchメソッドの主な引数

  • api_key (必須)
    APIアプリケーションキー※英数32文字
    (例) 0123456789abcdef0123456789abcdef
  • method (必須)
    実行メソッド名 flickr.photos.search (固定)
  • text (任意)
    フリーワードの全文検索を行う
  • user_id (任意)
    写真投稿者ユーザーIDで検索する
    (例) 50902562@N00
  • tags (任意)
    タグで検索する
  • tag_mode (任意)
    複数指定時の検索モード(デフォルト:any)
    anyOR検索
    allAND検索
  • min_upload_date (任意)
    アップロード日時(最小値=最も古い)絞込み
  • min_taken_date (任意)
    撮影日時(最小値=最も古い)絞込み
  • max_taken_date (任意)
    撮影日時(最大値=最も新しい)絞込み
  • bbox (任意)
    エリア(緯度経度)絞込み
    西端の経度,南端の緯度,東端の経度,北端の緯度の値を
    カンマ区切りで並べる(東経・北緯を正の値とする)。
  • (例) 139.70,35.61,139.78,35.74 (≒概ね山手線の内側)
  • sort (任意)
    並べ替え(デフォルト:date-posted-desc)
    date-posted-descアップロード日時の新しい順
    date-posted-ascアップロード日時の古い順
    date-taken-asc撮影日時の古い順
    date-taken-desc撮影日時の新しい順
    interestingness-desc人気の高い順
    interestingness-asc人気の低い順
    relevance関連度の高い順
  • extras (任意)
    追加出力項目(カンマ区切り)
    licenseライセンス種別
    date_uploadアップロード日時
    date_taken撮影日時
    owner_name投稿者名
    icon_serverアイコンサーバー
    original_formatアップロード時のフォーマット
    last_update更新日時
    geo緯度経度
  • per_page (任意)
    検索1回あたりの取得件数(デフォルト:100)
  • page
    出力ページ番号(デフォルト:1)
  • format (任意)
    出力フォーマット(デフォルト:rest)
    restXML形式 (RSP)
    jsonJSON / JSONP形式
    php_serialPHP serialize()形式
  • nojsoncallback (JSON形式)
    値が1の場合は,JSON/JSONP形式出力時に
    コールバック関数を呼び出さない(デフォルト:空)
  • jsoncallback (JSONP形式)
    JSON形式出力時のコールバック関数名

 このうち,api_key と method が必須です。 また,text,user_id,tags のいずれかで検索条件を指定します。 実際に,flickr.photos.searchメソッドを呼び出すJavaScriptコードは以下の通りです(リスト1)。

リスト1:flickr-search.js

// 画像検索を行う関数
function photo_search ( param ) {
    // APIリクエストパラメタの設定
    param.api_key  = '0123456789abcdef0123456789abcdef';
    param.method   = 'flickr.photos.search';
    param.per_page = 10;
    param.sort     = 'date-posted-desc';
    param.format   = 'json';
    param.jsoncallback = 'jsonFlickrApi';

    // APIリクエストURLの生成(GETメソッド)
    var url = 'http://www.flickr.com/services/rest/?'+
               obj2query( param );

    // script 要素の発行
    var script  = document.createElement( 'script' );
    script.type = 'text/javascript';
    script.src  = url;
    document.body.appendChild( script );
};

// 現在の表示内容をクリアする
function remove_children ( id ) {
    var div = document.getElementById( id );
    while ( div.firstChild ) { 
        div.removeChild( div.lastChild );
    }
};

// オブジェクトからクエリー文字列を生成する関数
function obj2query ( obj ) {
    var list = [];
    for( var key in obj ) {
        var k = encodeURIComponent(key);
        var v = encodeURIComponent(obj[key]);
        list[list.length] = k+'='+v;
    }
    var query = list.join( '&' );
    return query;
}

// Flickr検索終了後のコールバック関数
function jsonFlickrApi ( data ) {
    // データが取得できているかチェック
    if ( ! data ) return;
    if ( ! data.photos ) return;
    var list = data.photos.photo;
    if ( ! list ) return;
    if ( ! list.length ) return;

    // 現在の表示内容(Loading...)をクリアする
    remove_children( 'photos_here' );

    // 各画像を表示する
    var div = document.getElementById( 'photos_here' );
    for( var i=0; i<list.length; i++ ) {
        var photo = list[i];

        // a 要素の生成
        var atag = document.createElement( 'a' );
        atag.href = 'http://www.flickr.com/photos/'+
                    photo.owner+'/'+photo.id+'/';

        // img 要素の生成
        var img = document.createElement( 'img' );
        img.src = 'http://static.flickr.com/'+photo.server+
                  '/'+photo.id+'_'+photo.secret+'_s.jpg';
        img.style.border = '0';
        atag.appendChild( img );
        div.appendChild( atag );
    }
}

 このソースは,flickr-search.jsというファイル名で保存してください。 JavaScript ファイルの文字コードは,UTF-8 にしておくのが安全です。 冒頭の photo_search 関数で,検索パラメタを指定しています。

    param.api_key  = '0123456789abcdef0123456789abcdef';
    param.method   = 'flickr.photos.search';
    param.per_page = 10;
    param.sort     = 'date-posted-desc';
    param.format   = 'json';
    param.jsoncallback = 'jsonFlickrApi';

 まず api_key に,最初に取得した API Key を指定します。 正しく指定しないと,検索できませんので注意してください。 次の実行メソッド名(method)は,flickr.photos.search 固定です。 検索結果は100件も必要ないので,per_page で10件に制限します。 並べ替え(sort)は日付の降順ソートで,最新の写真を優先します。 出力フォーマット(format)は,JSON を指定します。 JSON読み込み完了後のコールバック関数名は,jsonFlickrApi とします。

 関数 remove_children は,写真の表示先要素をクリアします。 関数 obj2query は,キー:値のペアからなるJavaScriptオブジェクト(Perlで言う連想配列/ハッシュ)からURLエンコードのクエリー文字列を生成します。 どちらも今回以外でも利用できるような汎用的なルーチンです。

 最後の関数 jsonFlickrApi は,Flickr から届いた検索結果を受け取り,ブラウザ画面上に写真のサムネイルを表示する処理を行います。コールバック関数ですので,Flickr 側の検索処理が終わった時点(ブラウザにデータが到着した時点)で自動的に呼び出されます。

 リスト2は,flickr-search.jsの関数を利用するウェブページのサンプルです。

リスト2:search-hdr.html ⇒動作デモ

<html>
<head>
<title>Flickr APIによる画像検索<title>
<script type="text/javascript" src="flickr-search.js"></script>
<script type="text/javascript"><!--
    window.onload = function () {
        photo_search({ text: 'HDR' });
    }
--></script>
</head>
<body>

<div id="photos_here">Loading...</div>

</body>
</html>

 photos_here の中身は,ページを開いた段階では 「Loading...」と表示されています。 この部分を JavaScript による DOM 操作で書き換えて, Flickr の写真を10枚挿入する仕組みです。

 検索条件は { text: 'HDR' } の部分で指定しています。 タグや説明文に『HDR』というキーワードが含まれる写真を抽出します。 High Dynamic Range という手法で作成された 美しい画像が見つかるでしょうか?