プログラム上で、Amazonの書籍やDVDの検索、詳細、出荷時期、レビューの取得等ができるウェブサービスというAPIをAmazonは提供している。サイト側で動的な表示ができるという点で大変重宝するサービスで、各blogのAmazon plugin等はみんなこのサービスを使っているようだ。
ウェブサービスは他にもGoogleの検索・AdWordsや、オークションのBiddersも提供しているため、プログラムさえ組めば自サイトでGoogleの検索を利用したり、AdWordsの結果を知ったりキャンペーンを作ったり、Biddersの出品物を並べたりすることができる。
中でもAmazonが一番人気なのはアソシエイト(アフィリエイト)と組み合わせて実利に直結させることができるからだろう。
最近ではMac用の独立したアプリケーションまで存在するらしい。
私も以前PHPとnusoapを使って検索できるものを試しに作ったものの、そのままほったらかしていたのだが、ついにこの機能を実装する必要が出てきてしまったので、再度Amazonウェブサービスを弄る事となった。
取得したいデータは、「書籍名」「著者名」「新品価格」「ユーズド価格」「発送時期」「おすすめ度」「レビューした人数」で、複数のキーワードでの検索結果をマージして売れ筋ランキング順に10件分が必要。これらは、Amazon Webサービス ECS4.0だとオペレーションがItemSearch、SortがSalesRank、ResponseGroupを Medium,Reviews,Offerfull とすれば取得できる。
…いや、できるはずだった。
いざ PHP+nusoap.phpで取り組んでみたところ、売れ筋ランキング(SalesRank)がおかしい。ソート順をSalesRankとしても、一つ一つのデータを見てみるとSalesRankが昇順に並んでない。Google先生に聞いてみたところ、SalesRankでの結果はいつのランキングかわからないデータを元にしているらしい。
返される結果の順序が正しいのか、一つ一つの書籍が持っているSalesRankが正しいのか判断できないが、画面に表示される順位(とも必ずしも整合しないのだが)をベースにしたいと考えて、30位までのデータを取得後、各書籍のSalesRankを元にソートする事にした。これはこれで解決した事にしよう。
複数のキーワードで検索した場合に同じ書籍が登場する事があり、それは当たり前の事なので構わないのだが、同じ書籍なのに違うSalesRankが得られる事があった。データベースの更新時間帯だったのだろうか。この場合は、順位が上のものを優先する事にして解決。この方法だと、違う書籍でも同じ順位になる可能性があるが、そこまで厳密である必要はどこにもないので構わないだろう。
次に大きく悩んだのは「レビュー」の扱い。ResponseGroupにReviewsをつけたり、MediumをLargeに変えると結果が返ってこない…事がある。
検索キーワードによって結果が返ってきたり来なかったりで、このままだと正しい結果を得ることができない。例えばItemSearchでキーワードを[YMO]、mediaを[DVD]、ResponseGroupを[Reviews]にすると、結果が返ってこない。(このキーワードは一例で今回の仕事とは関係無い)
Google先生に聞いてみたところ、レビューのテキストの中に本来使用できない文字コードが混じってしまっていてエラーが発生しているらしい。発生した場合は、ECSフォーラムにASIN番号を書き込む事により修正してもらえるとの事で、より一般的な解決策も検討中との事。また、XSLTで結果を処理している場合にも弊害が生じるらしい。とりあえずパース中にエラーとなっているようだ。…Googleでは以上の事がわかった。
フォーラムで報告するのはやぶさかではないが、仕事なので未知のものにも対応しなければいけない。レビューが取得できないと、「おすすめ度」や「レビューした人数」を得ることができないぞ。う~ん、困った。
私がやってみた事
1. ItemSearchでItemIdsだけ取得し、ASINを元にItemLookupでデータを一つ一つ取得しなおす。
結果: 失敗
Reviewsで取得し損ねると10個のデータを失うが、この方法だと
レビューが取得できないアイテムだけ失うことになり被害は最
小限に留められる。しかし、データが揃わない事に代わりは無
いので意味が無い。
2. ECS4.0に問題があるのではないかと考えてECS3.0で組みなおす。
結果: 失敗
Largeに相当するheavyを指定するとやはり結果が返ってこない。
3. nusoap.phpをPEAR:SOAPに変えてみる。
結果: 失敗
ECS4.0 だと何故かparse errorが発生。PEAR:SOAPの方にバグ
レポートもあがっているようだが、如何ともしがたい。
ECS3.0 だとレビューが入っているデータは取得できない。
4. ECS4.0での取得をSOAPからRESTにしてみる。
結果: 失敗?
socketで接続してGETでパラメータを送信するとXMLな結果が
返ってきた。レビューも取得できてる。しかし、XMLparser
を通した時点でエラー発生。
必要な部分だけ自前で切り出せばOKそうだが、データが沢山
あるのでめんどくさそう。
なかなかうまくいかず時間を無駄にしたが、4.のあとでふと思いついた。
「取得したXMLデータの中からエラーの原因となるレビューの中身だけ削除しちゃえ!そうするとParserがちゃんと処理してくれるんでは!?」
「いやいや、いっその事 nusoap.php でその処理をしちゃえば普通にSOAPで扱えるのでは?」
という事で、1行追加して<Content></Content>間のデータを削除するようにしたところ、最初にやろうとした方法で必要なデータが得られることができるようになりました。今回はレビューの内容を使わないからいいんですけど、必要な時はどう処理すればいいんでしょうかね?その時は、また改めて考える事にします。
というわけで無事に処理できるようになりましたが、とても疲れました。レビューからイケナイ文字が早くなくなることを祈ってます。または、あってもエラーにならない抜本的な対策の早期導入を望みます。
追記(2005/2/13)
[
Amazon Web サービスがレビューの文字化けに対応]のエントリーで書きましたが、不正な文字が混ざると正しい結果が得られない不具合は、[2005-01-19バージョン]で修正され、nusoapを改造したり悩んだりすることなく正しいデータが得られるようになりました。お試しあれ。