Google AJAX Search APIのJSONPを利用したサイト内検索

Google AJAX Search APIは、動的にGoogle検索結果を自分のページに挿入することができるAPI(あまり使っているサイトを見ないけど)。Ajaxっつっても内部はJSONP(みたいなもの)だったりするので、普通にGwebSearchクラスのsetSiteRestriction()メソッドを使うのではなく、JSONPを直接叩いてサイト内検索を実装することもできる。もちろんサイト内検索に限った話ではないけど。

Google AJAX Search APIのGwebSearchクラスによる検索は、

http://www.google.com/uds/GwebSearch?callback={コールバック関数名}&context=0&lstkp=0&hl=ja&q={検索文字列}&key={Google AJAX Search API key}&v=0.1

というURLへリクエストすることによって検索結果を取得している。また、setSiteRestriction()メソッドによるサイト内検索は特別なURLへのリクエストではなく、検索文字列にsite:{ドメイン名}を追加しているだけ(ここらへんのことはLive HTTP Headersなんかでリクエストを監視していれば直ぐにわかる)。つまり、簡単な文字列の連結でリクエストするURLが作成できるので、コールバック関数さえ定義してやれば簡単にサイト内検索をすることができる。というわけでGoogle AJAX Search APIのJSONPを利用したサイト内検索のサンプルを作成してみた。

上記サンプルではgoogle-sitesearch.jsという外部JavaScriptファイルで実現している(prototype.jsやJSONPにリクエストするためのodj.jsとかいう自作ライブラリも使ってるけど)。google-sitesearch.jsでは、

var url = 'http://www.google.com/uds/GwebSearch?' + $H({
  lstkp:   0,
  context: 0,
  rsz:     'small',
  hl:      'ja',
  q:       $F('q') + ' site:hail2u.net',
  key:     apikey,
  v:       0.1
}).toQueryString();

とprototype.jsを使ってJSONPへのリクエストURLを作成しているが、もちろん文字列の連結とかでも問題ない(encodeURIComponent()する必要はあるけど)。コールバック関数は、

function handleGwebSearchResults(i, r, n, m) {
  r.results.each(function (result) {
    // 各検索結果に対する処理
  });
}

と四つ引数があることと第二引数に検索結果が格納されていることを意識して作れば良い。prototype.jsのArrayクラスに対する拡張のeach()メソッドとか使ってるけど、普通にforループでも書ける。各検索結果は、

{
  GsearchResultClass:"GwebSearch",
  unescapedUrl : "http://hail2u.net/archives/bsk.html",
  url : "http://hail2u.net/archives/bsk.html",
  visibleUrl : "hail2u.net",
  cacheUrl : "http://www.google.com/search?q=cache:2EslMvGB3FEJ:hail2u.net",
  title : "hail2u.net - Archives - <b>blosxom</b> starter kit",
  titleNoFormatting : "hail2u.net - Archives - blosxom starter kit",
  content : "できることならこれを利用し、<b>blosxom</b>の挙動を知った上で、一から<b>blosxom</b>を構築すること<br>  をお薦めします。 <b>...</b> オリジナルの<b>blosxom</b>の使い方については説明する気はないです。<br>  公式サイトで公開されているプラグインも、オリジナルで使うときと同様に利用 <b>...</b>"
}

という明快な構造になっているので、あとは適当にHTMLを作って吐き出すだけ。特に難しいところはない。ただ、Google AJAX Search APIでは最高でも8件までしか検索結果を取得することができないので、8件以上検索結果がありそうな場合は、最後にGoogleのサイトへ誘導するリンクを付け足すようにした(startパラメータを利用して検索結果を重ならないようにしてある)。このサイトくらいの規模ならば8件とかでも充分だったりするのだけれども。

実際にこういった検索結果を動的に挿入云々をサイトで実装したい場合は、公式にJSON(P)がサポートされているYahoo! Search Web ServicesのWeb Searchを利用するべき(Yahoo! Search Web ServicesのJSONPを利用したサイト内検索のサンプル)。ただ、サイト内検索なんかではGoogleの方が明らかに検索結果が優秀なイメージがあって悩ましい。とりあえずYahoo!のSite Explorerでサイトマップ送信してみた。改善したらうれしい。