wiki:PyAmazon

Version 8 (modified by atzm, 18 years ago) (diff)

--

PyAmazon

 http://www.josephson.org/projects/pyamazon/

仕様が割とひどい.

基本

以下は amazon.co.jp から「のだめ」を検索した結果を適当に出力する例.

検索キーワードには UTF-8 文字列 (unicode オブジェクトではない) を指定してやる必要がある.

import amazon

LOCALE = 'jp'
ACCESS_KEY = 'your access key'

amazon.setLocale(LOCALE)
amazon.setLicense(ACCESS_KEY)

data = amazon.searchByBlended(unicode('のだめ', 'euc-jp').encode('utf-8'))

for p in data.ProductLine:
    details = p.ProductInfo.Details
    for d in details:
        for key, val in d.__dict__.iteritems():
            print '%(key)s: %(val)s' % locals()

searchByKeyword の罠

searchByKeyword 関数で,あるカテゴリの中から検索することができる.

  • しかし,searchByBlended と違って data をそのまま返さずに data.Details を返しやがる (amazon.py の 312 行目を参照) ので,searchByKeyword を使うと,TotalPages や TotalResults を得ることができない.
  • さらに,searchByKeyword の引数に,デフォルトで product_line="books" というのが入っているが,ロケールを jp にした場合はこれだと正しく検索できない.jp ロケールで有効な product_line は以下の通り (たぶん).
books-jp和書
books-us洋書
music-jpポピュラー音楽
classical-jpクラシック音楽
dvd-jpDVD
vhs-jpビデオ
electronics-jpエレクトロニクス
kitchen-jpホーム&キッチン
software-jpソフトウェア
videogames-jpゲーム
magazines-jp雑誌
toys-jpおもちゃ&ホビー
photo-jp
pc-hardware-jp

searchByBlended の罠

searchByBlended 関数は amazon に対して全体検索をかけることが可能.

searchByKeywords のように,この関数にも引数に page というのがある.

が,あたかもページを指定できるのかと思いきや,できない.これは Amazon API 側の仕様のようだ.

何のための引数なのか,かなり謎.

データの整合性

変数のあるなし

PyAmazon は内部で Amazon API の XML を呼び出して xml.dom.minidom で解析した後,unmarshal という関数で階層構造に沿ってオブジェクトを作っている.そのため,XML の構造がそのまま Python のオブジェクトに継承されている.

そのせいか,結果によってあったりなかったりする要素があるので,適切なエラー処理を書く必要がある.

data = amazon.searchByBlended(unicode('のだめ', 'euc-jp').encode('utf-8'))
d = data.ProductLine[0].ProductInfo.Details[0]

d.ProductDescription                    # AttributeError を引き起こす可能性が高い
getattr(d, 'ProductDescription', None)  # こちらの方が安全

型の整合性

たとえば Artists.Artist の中身が list になったり str になったりする.ちゃんと処理してやらないとハマる.

ATTRS = ['Authors', 'Artists', 'Tracks']

data = amazon.searchByBlended(unicode('のだめ', 'euc-jp').encode('utf-8'))
d = data.ProductLine[2].ProductInfo.Details[0]

for attr in ATTRS:
    print '%s: ' % attr
    authors = getattr(d, attr, None)
    if isinstance(authors, amazon.Bag):
        authors = getattr(authors, attr[:-1], None)
        if isinstance(authors, list): # リストの場合
            for a in authors:
                print '  %s' % a
        elif authors is not None: # リストでも None でもない場合は str と仮定
            print '  %s' % authors