人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

PythonでAmazon Product Advertising APIを使う

以前、Amazon Web Serviceで書籍情報を取得する(2008/12/20)というエントリを書きましたが、2009年8月15日から新しく認証が導入されてそのままでは使えなくなっていることに気がつきました。サービス名もProduct Advertising APIに変更されたそうです。AmazonのWebサービスはときどき使いたくなるのでPythonから使う方法を改めて調べてみました。以下のサイトを参考にさせていただきました。

amazon.py

まず、Pyzonを参考にアイテムID(ASIN、ISBNなど)を元に商品の詳細情報を取得したり、キーワードをもとに商品を検索するための基本的なAmazonクラスを作成。Pyzonのサブセットみたいな感じです。ちゃんと、認証用のシグネチャも生成して、RESTのリクエストURLに追加しています。

#coding:utf-8
import urllib2
import hashlib, hmac
import base64
import time

"""
Amazon Product Advertising APIを使って商品情報を取得する
"""

class Amazon:
    def __init__(self, access_key, secret_access_key, associate_tag=None):
        """コンストラクタ"""
        self.amazonurl = "http://webservices.amazon.co.jp/onca/xml"
        self.proxy_host = None
        self.proxy_port = None
        self.access_key = access_key
        self.secret_access_key = secret_access_key
        self.associate_tag = associate_tag
        self.version = "2009-10-01"
        self.url = None
    
    def setProxy(self, host, port=8080):
        """プロキシをセット"""
        self.proxy_host = host
        self.proxy_port = port
    
    def setVersion(self, version):
        """バージョンをセット"""
        self.version = version
    
    def itemLookup(self, item_id, **options):
        """アイテムの詳細情報を取得"""
        params = options
        params["Operation"] = "ItemLookup"
        params["ItemId"] = item_id
        return self.sendRequest(params)
    
    def itemSearch(self, search_index, **options):
        """アイテムを検索"""
        params = options
        params["Operation"] = "ItemSearch"
        params["SearchIndex"] = search_index
        return self.sendRequest(params)
    
    def buildURL(self, params):
        """RESTリクエストのURLアドレスを構築"""
        params["Service"] = "AWSECommerceService"
        params["AWSAccessKeyId"] = self.access_key
        if self.associate_tag is not None:
            params["AssociateTag"] = self.associate_tag
        params["Timestamp"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
        sorted_params = sorted(params.items())
        
        # paramsのハッシュを展開
        request = []
        for p in sorted_params:
            pair = "%s=%s" % (p[0], urllib2.quote(p[1].encode("utf-8")))
            request.append(pair)
        
        # 2009/8/15から認証が導入されている
        # Secret Access Keyを使ってHMAC-SHA256を計算
        msg = "GET\nwebservices.amazon.co.jp\n/onca/xml\n%s" % ("&".join(request))
        hmac_digest = hmac.new(self.secret_access_key, msg, hashlib.sha256).digest()
        base64_encoded = base64.b64encode(hmac_digest)
        signature = urllib2.quote(base64_encoded)
        
        # Signatureをリクエストに追加してURLを作成
        request.append("Signature=%s" % signature)
        url = self.amazonurl + "?" + "&".join(request)
        
        return url
        
    def sendRequest(self, params):
        """Amazonにリクエストを送付し、取得したXMLを返す"""
        self.url = self.buildURL(params)
        if self.proxy_host:
            proxy_handler = urllib2.ProxyHandler({"http":"http://%s:%s/" % (self.proxy_host, self.proxy_port)})
            opener = urllib2.build_opener(proxy_handler)
        else:
            opener = urllib2.build_opener()
        return opener.open(self.url).read()

キーワードで本を検索したい!

Amazon APIを使うにはAccess Key IDSecret Access Keyが必要になります。登録はここから行えます。Secret Access Keyはシグネチャの秘密鍵なので公開してはダメです。そんなわけで下のプログラムでは自分で取得したIDを使ってください。あと下のサンプルプログラムは、Amazonから返ってきたXMLのパースにBeautifulSoupを使っています。めちゃくちゃ便利なのでぜひ導入したほうがいいです。

では、Amazonクラスを使って「人工知能」というキーワードで本を検索してみます。

#coding:utf-8
from amazon import Amazon

# キーワードで本を検索したい!
amazon = Amazon("[自分のAccess Key使ってね!]", "[自分のSecret Access Key使ってね!]")
xml = amazon.itemSearch("Books", Keywords="人工知能", ItemPage="1")  # 本
print amazon.url  # リクエストURL
#print xml        # Amazonのレスポンス

# XMLから情報を取り出す
from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(xml)

items = soup.find("items")
print "%s件見つかりました" % soup.find("totalresults").contents[0]
total_pages = soup.find("totalpages").contents[0]
cur_page = soup.find("itempage").contents[0]
print "ページ数: %s/%s" % (cur_page, total_pages)

for item in soup.findAll("item"):
    print item.asin.contents[0], item.author.contents[0], item.title.contents[0]

実行結果は、下のようになります。

http://webservices.amazon.co.jp/onca/xml?AWSAccessKeyId=0CDQFTTPS2NZ96X08C02&ItemPage=1&Keywords=%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD&Operation=ItemSearch&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2010-01-16T12%3A55%3A51Z&Signature=yezZ2JcRjzwys3G1%2B7eWXFc/U8aHYzYh7EQR729kS18%3D
741件見つかりました
ページ数: 1/75
4320121163 荒屋 真二 人工知能概論 第2版 ―コンピュータ知能からWeb知能まで
4320122151 S.J.Russell エージェントアプローチ人工知能 第2版
4270000600 ジェフ・ホーキンス 考える脳 考えるコンピューター
4883170802 森川 幸人 マッチ箱の脳(AI)―使える人工知能のお話
4627803028 菅原 研次 人工知能 (情報工学入門シリーズ)
4757211015 スティーヴ・グランド アンドロイドの脳 人工知能ロボット"ルーシー"を誕生させるまでの簡単な20のステップ
4764901455 太原 育夫 人工知能の基礎知識 (コンピュータサイエンス大学講座)
4339023876 新谷 虎松 Javaによる知能プログラミング入門
4274201066 松本 一教 人工知能 (IT Text)
4274066649 小高 知宏 はじめてのAIプログラミング―C言語で作る人工知能と人工無能

1回のリクエストでは10件しか取得できないみたいです。2ページ目以降の検索結果を取得するにはItemPageパラメータを変更して再度リクエストを出す必要があります。

ISBNで本の情報を取得したい!

ASINやISBNを使ってさらに本の詳細情報を取得できます。下の例では、本についている13桁のISBNを使って検索してます。IdTypeをASINにすれば、ASINでも検索できます。さっきの4320121163とかがASINです。

#coding:utf-8
from amazon import Amazon

# ISBNで本の情報を取得したい!
amazon = Amazon("[自分のAccess Key使ってね!]", "[自分のSecret Access Key使ってね!]")
xml = amazon.itemLookup("9784431100133", SearchIndex="Books", IdType="ISBN", ResponseGroup="Large,Similarities", ReviewPage="1")  # 本
print amazon.url  # リクエストURL
#print xml                         # Amazonのレスポンス

# XMLから情報を取り出す
from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(xml)
item = soup.find("item")

# 商品情報
print item.asin                   # Amazon商品コード
print item.detailpageurl          # 商品ページのURL
print item.smallimage.url         # 小画像へのURL
print item.mediumimage.url        # 中画像へのURL
print item.largeimage.url         # 大画像へのURL
print item.largeimage.height      # イメージの高さ
print item.largeimage.width       # イメージの幅

# 商品属性
print item.itemattributes.findAll("author")         # 著者リスト
print item.itemattributes.findAll("creator")        # 作者
print item.itemattributes.ean                       # EAN
print item.itemattributes.isbn                      # ISBN
print item.itemattributes.listprice.amount          # 価格
print item.itemattributes.publicationdate           # 出版日
print item.itemattributes.publisher                 # 出版局
print item.itemattributes.title                     # タイトル
print item.itemattributes.numberofpages             # ページ数

# レビュー関係
print item.customerreviews.averagerating            # 平均レイティング
print item.customerreviews.totalreviews             # レビュー数
print item.customerreviews.totalreviewpages         # レビューページ数

# レビュー本文
for review in item.customerreviews.findAll("review"):
    print review.summary, review.rating  # 要約とレイティング
#    print review.content                 # レビュー本文

# 関連商品
for similar in item.similarproducts.findAll("similarproduct"):
    print similar.asin, similar.title

実行結果は、下のようになります。いろんな情報が取得できます。

http://webservices.amazon.co.jp/onca/xml?AWSAccessKeyId=0CDQFTTPS2NZ96X08C02&IdType=ISBN&ItemId=9784431100133&Operation=ItemLookup&ResponseGroup=Large%2CSimilarities&ReviewPage=1&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2010-01-16T12%3A59%3A48Z&Signature=IERGvNZpi2A0dpOaV/nw9ZuzeMzPF0tirC%2BcW3k1iD4%3D
<asin>443110013X</asin>
<detailpageurl>http://www.amazon.co.jp/%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E8%AA%8D%E8%AD%98%E3%81%A8%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E3%83%99%E3%82%A4%E3%82%BA%E7%90%86%E8%AB%96%E3%81%AB%E3%82%88%E3%82%8B%E7%B5%B1%E8%A8%88%E7%9A%84%E4%BA%88%E6%B8%AC-C-M-%E3%83%93%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97/dp/443110013X%3FSubscriptionId%3D0CDQFTTPS2NZ96X08C02%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D443110013X</detailpageurl>
<url>http://ecx.images-amazon.com/images/I/41z0AD06ZaL._SL75_.jpg</url>
<url>http://ecx.images-amazon.com/images/I/41z0AD06ZaL._SL160_.jpg</url>
<url>http://ecx.images-amazon.com/images/I/41z0AD06ZaL.jpg</url>
<height units="pixels">459</height>
<width units="pixels">300</width>
[<author>C. M. ビショップ</author>]
[<creator role="翻訳">元田 浩</creator>, <creator role="翻訳">栗田 多喜夫</creator>, <creator role="翻訳">樋口 知之</creator>, <creator role="翻訳">松本 裕治</creator>, <creator role="翻訳">村田 昇</creator>]
<ean>9784431100133</ean>
<isbn>443110013X</isbn>
<amount>6825</amount>
<publicationdate>2007-12-10</publicationdate>
<publisher>シュプリンガー・ジャパン株式会社</publisher>
<title>パターン認識と機械学習 上 - ベイズ理論による統計的予測</title>
<numberofpages>349</numberofpages>
<averagerating>3.5</averagerating>
<totalreviews>2</totalreviews>
<totalreviewpages>1</totalreviewpages>
<summary>オリジナルに劣る...</summary> <rating>2</rating>
<summary>機械学習の新・定番教科書,待望の邦訳!</summary> <rating>5</rating>
<asin>4431100318</asin> <title>パターン認識と機械学習 下 - ベイズ理論による統計的予測</title>
<asin>4431727388</asin> <title>統計のための行列代数 下 (2)</title>
<asin>443172737X</asin> <title>統計のための行列代数 上 (1)</title>
<asin>4627847114</asin> <title>フリーソフトでつくる音声認識システム - パターン認識・機械学習の初歩から対話システムまで</title>
<asin>4000069713</asin> <title>カーネル多変量解析―非線形データ解析の新しい展開 (シリーズ確率と情報の科学)</title>

titleとかのタグがいらない場合は、

print item.itemattributes.title.contents[0]  # タイトル

とcontents[0]をつければOKです。画像はURLがわかるのでurllib2でアクセスしてjpegを取得できます。このAPIでは、本以外にもいろんな情報が取得できます。詳しくは開発者ガイド(英語)を参照してください。