2007年06月04日

ISBNでAmazon ECS検索

慣れない言語に四苦八苦しながら(といいつつ、かなり楽しんでいる)、Amazon ECSからデータを引っ張ってくるクラスを書いてみた。
まだRubyに不慣れなので、かなりアレなコードだと思われるが、夢中になってるとブログに書くのも忘れるので、とりあえずのネタとして。

require 'net/http' require 'cgi' require 'rexml/document' class AmazonEcs attr_reader :error_code, :error_message @@common_params = { :Service => 'AWSECommerceService', :AWSAccessKeyId => 'XXXXXXXXXXXXXXXXXXXX', :Version => '2007-05-14', :AssociateTag => 'xxxxxxxxxxx', :Operation => 'ItemSearch', :ResponseGroup => 'Medium,BrowseNodes' }; def initialize(book) @sw = SearchWord.new @sw.set_by_book(book) end def item_search h = {} @@common_params.each do |key,val| h[key] = val end if @sw.isbn.blank? h[:SearchIndex] = 'Books' h[:Title] = @sw.title unless @sw.title.blank? h[:Author] = @sw.author unless @sw.author.blank? h[:Keyword] = @sw.keyword unless @sw.keyword.blank? @response_node_name = 'ItemSearchResponse' else h[:SearchIndex] = 'Books' if @sw.isbn.length > 10 h[:IdType] = 'ISBN' if @sw.isbn.length > 10 h[:Operation] = 'ItemLookup' h[:ItemId] = @sw.isbn @response_node_name = 'ItemLookupResponse' end url = mk_url(h) @xml = aws_request(url) if has_xml_error?() return nil end first_ecs_book() end def mk_url(h) # RESTで必要なパラメータをURL形式に変更 arr = [] h.each do |key,val| arr << key.to_s + "=" + CGI::escape(val.to_s) end paramString = arr.join('&') URI.parse("http://webservices.amazon.co.jp/onca/xml?" + paramString) end def aws_request(url) return REXML::Document.new(Net::HTTP.get(url)) end def has_xml_error? # エラーチェック xpath = "ItemSearchResponse/Items/Request/Errors/Error" @xml.get_elements(xpath).each do |element| @error_code = element.text('Code') @error_message = element.text('Message') return true; end return false; end def first_ecs_book xpath = "#{@response_node_name}/Items/Item" @xml.get_elements(xpath).each do |element| ecs_book = EcsBook.new ecs_book.asin = element.text('ASIN') ecs_book.isbn = element.text('ItemAttributes/ISBN') ecs_book.title = element.text('ItemAttributes/Title') ecs_book.author = element.text('ItemAttributes/Author') ecs_book.manufacturer = element.text('ItemAttributes/Manufacturer') ecs_book.binding = element.text('ItemAttributes/Binding') ecs_book.publication_date = element.text('ItemAttributes/PublicationDate') ecs_book.small_image_url = element.text('SmallImage/URL') ecs_book.medium_image_url = element.text('MediumImage/URL') ecs_book.large_image_url = element.text('LargeImage/URL') ecs_book.detail_page_url = element.text('DetailPageURL') return ecs_book end nil end end

中で使われている、SearchWordとEcsBookというクラスはそれぞれ、画面からの検索情報を渡すためのプレースホルダー、およびAmazonECSからの結果を保持し、DBへ格納するためのActiveRecordです。

ISBNが指定されている場合は、優先してISBN検索をするようにしたのだが、最近買った本(具体的には泣き虫弱虫諸葛孔明第弐部)のISBNを入れてみたところ、うまくいかない。

この本はISBNが従来の10桁ではなく13桁になっている(詳しくはWikipediaを参照のこと)。

ISBNが11桁以上だったら、IdTypeパラメータをISBNに設定(このとき、SearchIndexパラメータも必要となる)すると、ItemLookupオペレーションが動くことを発見。ちなみに10桁のISBNは、ASINと一致なので、IdTypeはASIN、もしくは指定しない(=ASIN)である。ASINの場合、面倒だがSearchIndexパラメータが指定されると逆にエラーとなる。
APIドキュメントによると、JPではIdType=ISBNはサポートされてないことになっているが、使えるから良いか。

どうせなら10桁の時も、IdType=ISBNで取得させてくれれば楽だと思うのだが、そうはなっていない。

投稿者 iwazawa : 2007年06月04日 02:33 | トラックバック
コメント
コメントする









名前、アドレスを登録しますか?