camel

久々の勝手に添削コーナ。今回は、hyukiさんのこちら。

結城浩のはてな日記
Amazon Web Servicesを使って、ISBN-13からASINを取得するPerlプログラムを作ってみました。

まずは添削結果。

#!/usr/local/bin/perl
use strict;
use warnings;

use CGI;
use LWP::Simple;
use XML::Simple;
use URI;

my $aws_access_key_id = 'YOUR AWS ACCESS KEY';

# For debug.
my $OUTPUT_ENCODING = 'UTF8';

# Set up ISBN.
my $isbn = shift or die "$0 [ISBN]";

# Set up URL.
my $uri = URI->new('http://webservices.amazon.co.jp/onca/xml');
$uri->query_form(
    Service        => "AWSECommerceService",
    AWSAccessKeyId => $aws_access_key_id,
    Operation      => "ItemLookup",
    IdType         => "ISBN",
    ItemId         => $isbn,
    SearchIndex    => "Books",
    ResponseGroup  => "Request,Small",
    Version        => "2007-01-15",
);

# Retrieve result.
print "ISBN: $isbn\n";
my $response_string  = get($uri);
my $response_hashref = XMLin($response_string);

# Compose output string.
my $output = <<"EOD";
ASIN: $response_hashref->{Items}->{Item}->{ASIN}
Title: $response_hashref->{Items}->{Item}->{ItemAttributes}->{Title}
Author: $response_hashref->{Items}->{Item}->{ItemAttributes}->{Author}
EOD

# Print as string.
binmode STDOUT => ":encoding($OUTPUT_ENCODING)";
print $output;
__END__

ポイントはURIを文字列でなくてURIオブジェクトで処理していること。これのquery_form()メソッドを使うと、このようにquery部分がすっきりと書けます。あと、ISBNの指定は決め打ちではなく引数にしてあります。

さすがhyukiさんだけあって、添削するほど汚いコードではないのですが、URIモジュールはLWPを煎れればもれなく付いてくるので紹介した次第です。

おまけ

AJAX版を以下に作ってみました。

ISBN:
ASIN:
Title:
Author:
JS+HTML部分は以下のとおり。
function $(id){ return document.getElementById(id) };
ISBN2ASIN = function(proxy, callback){
  this.proxy     = proxy || 'http://www.dan.co.jp/~dankogai/aws/isbn2asin.cgi';
  this.callback  = callback || 'jsonp';
  this.parse = function(isbn, callback){
    if (! callback) callback = this.callback;
    var script = document.createElement('script'); 
    script.id = this.proxy + '/' + callback + '/' + isbn;
    script.charset = 'UTF-8';
    script.src = script.id; 
    document.lastChild.appendChild(script);
  };
  return this;
}
var isbn2asin = new ISBN2ASIN();
function parse_jsonp(jsonp){
  if (jsonp.Items.Request.IsValid == "False"){
    $('aws.asin').innerHTML   = jsonp.Items.Request.Errors.Error.Message;
    $('aws.title').innerHTML  = '';
    $('aws.author').innerHTML = '';
  }else{
    $('aws.asin').innerHTML   = jsonp.Items.Item.ASIN;
    $('aws.title').innerHTML  = jsonp.Items.Item.ItemAttributes.Title;
    $('aws.author').innerHTML = jsonp.Items.Item.ItemAttributes.Author;
  }
}
</script>

<table style="border: outset 1px; padding: 0.5em">
<tr><td>ISBN:</td><td><input id='isbn' type="text" value="978-4844322894">
  <input type="submit" onclick="isbn2asin.parse($('isbn').value, 'parse_jsonp')"></td></tr>
<tr><td>ASIN:</td><td id="aws.asin"></td></tr>
<tr><td>Title:</td><td id="aws.title"></td></tr>
<tr><td>Author:</td><td id="aws.author"></td></tr>
</table>

サーバー側のisbn2asin.cgiはリンクしておくに留めます。

Enjoy!

Dan the Just Another AWS Hacker

See Also: