jQuery + Bing APIで動画検索するコード書いてみた

Bing APIでjsonpを使って動画検索するコードを書いてみた。個人的にはちょっと使えないかもなーって感じだったのだけどせっかくなのでまとめて公開してみる。

まずBing APIを使うにはアプリケーションIDが必要になる。下記の Create an AppID ってとこから取得できる。Live IDが必要になるが簡単にとれる。

http://www.bing.com/developers/ とったアプリケーションIDをクエリのパラメータに含めることになる。API Basicってドキュメントの終わりの方にやんないといけないこと、やっちゃいけないこととか書いてあり、その中にリクエストはIPごとに1秒間に7回以下に抑えろとある。このアプリケーションIDとIPで計測されたりするのだろう。

Restrict your usage to less than 7 queries per second (QPS) per IP address. You may be permitted to exceed this limit under some conditions, but this must be approved through discussion with api_tou@microsoft.com.

IPごととか言われると、サーバサイドでやるよりクライアントサイドでやった方がいいよね。って話になるので今回はjsonpを使う。

まずjQueryにjQuery.ajaxライクなbing関数を拡張。

/*
* jquery.bing
*
* Copyright (c) 2009 makoto_kw (makoto.kw@gmail.com)
* Dual licensed under the MIT and GPL licenses.
*
* Version: 1.0
*/
(function($) {
  $.extend({
    /* options = {
    * appId: 'xxxxx',
    * query: 'sushi',
    * sources: 'web',
    * offset: 0,
    * count: 10,
    * callback: function(data){}
    * }
    */
    bing: function(options) {
      var sources = options.sources || 'web';
      var params = {
        AppId: options.appId,
        query: options.query,
        sources: sources
      };
      if (sources.indexOf('+')==-1) {
        params[sources+'.offset'] = options.offset || 0;
        params[sources+'.count'] = options.count || 10;
      } else {
        // TODO:
      }
      // video
      if (sources.indexOf('video')!=-1) {
        params['video.sortby'] = options.video_sortby || 'Relevance'; // Relevance or Date
      }
      $.getJSON('http://api.search.live.net/json.aspx?Jsontype=callback&Jsoncallback=?', params, options.callback);
    }
  });
})(jQuery);

一応こんな感じで使う。callbackではBing APIのレスポンスを特に整形していないまま渡す。ちなみにリクエスト先はhttp://api.search.live.net/になっていて、bingってブランドはついてるけど実際にはlive searchのmajor version upって扱いかな。

$.bing({appid:\'Your AppID\', query:\'sushi\',callback:function(data){
//
});

で、動画の検索をするときはsourceにvideoを指定する(デフォルトはweb)。特定の動画サイトで検索する場合はクエリに(filterui:msite-nicovideo.jp OR filterui:msite-dailymotion.com OR filterui:msite-youtube.com)を追加すればよい。

フォームと合わせてサンプルを書いてみる。

<table><tr><td width="100%">
  <p>bingで動画検索</p>
  <form id="search_form" method="POST">
    <input id="search_keyword" name="search_keyword" value="Janne Da Arc"/>
    <select id="sortby" name="sortby">
      <option value=Relevance>Relevance</option>
      <option value="Date">Date</option>
    </select>
    <input type="submit" value="SEARCH"/>
    <br style="clear:both"/>
  </form>
  <div id="search_results"></div>
</td>
<td width="200"></td></tr></table>
<script>
(function($) {
  $(document).ready(function(){
    var $form = $('#search_form'), $input = $('#search_keyword'), $results = $('#search_results');
    var $sortby = $('#sortby');
    $form.bind('submit', function() {
      $form.find('.error_list').remove();
      var keyword = $input.val();
      if (keyword=='') {
        $form.prepend('<ul class="error_list"><li>キーワードを入力してください</li></ul>');
        return false;
      }
      $results.html('<div class="video_loading">NOW LOADING...</div>');
      $.bing({
        appId:'Your AppID',
        query:keyword+' (filterui:msite-nicovideo.jp OR filterui:msite-dailymotion.com OR filterui:msite-youtube.com)',
        sources:'video',
        video_sortby:$sortby.val(),
        count:20,
        callback: function(data) {
          var $videos = $('<ul class="video_list"/>');
          var video = data.SearchResponse.Video;
          var total = video.Total || 0, offset = video.Offset || 0, items = video.Results || [];
          for (var i=0, len=items.length; i<len; i++) {
            var v = items[i];
            var thumb = v.StaticThumbnail || {};
            var thumbWidth = 160, thumbHeight = 120;
            if (thumb.Height>0) {
              thumbHeight = Math.min(120, thumb.Height);
              thumbWidth = Math.floor(120*thumb.Width/thumb.Height);
            }
            var $a = $('<a/>').attr('href',v.PlayUrl).attr('rel',v.SourceTitle).
            click(function(e){
              e.stopImmediatePropagation();
              return false;
            });
            var date = new Date(v.RunTime);
            var tm = date.getMinutes(), ts = date.getSeconds();
            if (tm<10) tm = '0'+tm;
            if (ts<10) ts = '0'+ts;
            var duration = tm  + ':' + ts;
            $videos.append($('<li class="rowvideo"/>')
              .append($('<div/>').append($a.clone(true).html('<img src="'+thumb.Url+'" width="'+thumbWidth+'" height="'+thumbHeight+'"/>')))
              .append($('<div/>').append($a.clone(true).html(v.Title))).append('<span class="source">'+v.SourceTitle+'</span><span class="duration">'+duration+'</span>')
              );
          }
          $results.empty().append($videos);
        }
      });
      return false;
    });
  });
})(jQuery);
</script>

これはニコ動とYouTubeとDailyMotionの動画を検索するサンプル。
サクサク動いて良い感じなんだけど、ソートがRelevanceかDateしかないのが不便なところ。動画の場合再生数とかでソートしたくなるのでものによってはやっぱりYouTube DATA APIを使うほうが良い場合もありそう。