Google AJAX Search API ってその名の通り JavaScript から利用することを前提に作られているんだけど、 先ほどドキュメンテーションに「Flash and other Non-Javascript Environments」という項目が追加されました。 JavaScript 以外の環境から Google AJAX Search API をこんな風に使えますよと書かれているようです。 今まで、例えば Perl から Web ページを検索する時には、Google のそれは「JS からしか使えないんでしょ」とあきらめて、Yahoo! の検索 API をよく使っていたところ、これで Google の検索結果も利用できるようになります。 JavaScript のレイヤーより一つ下くらいのところで、API が使えるとなると可能性も広がるかと思います。 ということで、早速、WebService::Simple を使って、Perl から Google AJAX Search API を使ってみたよ。
サンプルを紹介する前にこの API の仕様について軽く解説。 ベースURL は
http://ajax.googleapis.com/ajax/services/search/web
で、それに以下のようなパラメータを渡すと結果が JSON 形式で返ってくる。
q : 検索クエリー
v : API のヴァージョン、現時点でのデフォルトは 1.0
rsz : 検索結果をどのサイズで返して欲しいか、デフォルトは small の4件、large を指定すると8件
hl : 何語のウェブから検索したいか、日本語の場合だと ja
start : 検索結果を何番目から取得したいか、デフォルトは 0、おそらく最大で 24 っぽい
詳しくはここを参照→Class Reference - Google AJAX Search API - Google Code
取得できる JSON の形式はこちらを参考に→Developer's Guide - Google AJAX Search API - Google Code
では、WebService::Simple を使ったサンプルを紹介。 WebService::Simple には JSON のパーサーもあるので検索結果を Dump するだけのスクリプトだったらこんな簡単に書けちゃいます。
my $google = WebService::Simple->new( base_url => "http://ajax.googleapis.com/ajax/services/search/web", response_parser => "JSON", params => { v => "1.0", rsz=> "large" } ); my $response = $google->get( { q => "cat" , start=> 0 } ); print Dump $response->parse_response;
次に、検索クエリーを入れるとその結果が表示されるだけの簡単な Web ページを作ってみます。 パースしたコンテンツをそのまま Template::Toolkit のテンプレートに渡すという方針です。 ただ、これを実現するにはちょっとしたハックが必要になりました。 JSON のモジュールを使ってパースされたオブジェクトには utf8 フラグが立ってないっぽいんですよ。 utf8 flagged な値も、TT に渡したいので、混在しちゃうと文字化けしちゃいます(その値を uri フィルターかけたいから、フラグを落としたくないのです、なんか間違ってたらツッコミください)。 そこで、以下のハックで JSON モジュールが返してくれるオブジェクトに utf8 フラグを立ててます。
use WebService::Simple; use WebService::Simple::Parser::JSON; my $parser = WebService::Simple::Parser::JSON->new; # パーサーを作る $parser->{json}->utf8(1); # utf8 フラグが立ったオブジェクトを返してもらう my $google = WebService::Simple->new( base_url => "http://ajax.googleapis.com/ajax/services/search/web", response_parser => $parser, # パーサーオブジェクトを指定する params => { v => "1.0", rsz => "large", hl => "ja" } );
つまづいたのはこのくらい。完成版のPerl のコードと テンプレートは以下の通りです。
search.cgi
#!/usr/bin/perl use strict; use warnings; use CGI; use Template; use WebService::Simple; use WebService::Simple::Parser::JSON; my $q = CGI->new; my $query = $q->param('query'); utf8::decode($query); my $start = $q->param('start') || 0; my $parser = WebService::Simple::Parser::JSON->new; $parser->{json}->utf8(1); my $google = WebService::Simple->new( base_url => "http://ajax.googleapis.com/ajax/services/search/web", response_parser => $parser, params => { v => "1.0", rsz => "large", hl => "ja" } ); my $response = $google->get( { q => $query, start => $start } ); my $tt = Template->new(); my $html; $tt->process( "search.tt", { query => $query, response => $response->parse_response }, \$html ); print $q->header( -type => "text/html", -charset => "utf-8" ); print $html;
search.tt
<html> <body> <h1><a href="search.cgi">Google Search</a></h1> <form action="" method="get"> <p> <input type="text" name="query" value="[% query %]" /> <input type="submit" value="Google Search" /> </p> </form> <p> [% SET count = response.responseData.cursor.estimatedResultCount -%] [% IF count -%][% count %] pages[% END -%] </p> <dl> [% FOREACH item = response.responseData.results -%] <dt><a href="[% item.unescapedUrl %]">[% item.title %]</a></dt> <dd>[% item.content %]</dd> [% END -%] </dl> <div> [% FOREACH page = response.responseData.cursor.pages -%] <a href="?query=[% query | uri %]&start=[% page.start %]">[% page.label %]</a> [% END -%] </div> </body> </html>
ということで、Google AJAX Search API を WebService::Simple 使って利用してみました。 取得できる件数に制限があるのがちょっと残念ですが、この API なかなか重宝しそうです。