はじめに

今回は、Amazonで書籍情報を検索する方法を説明します。多岐にわたる取扱商品の中から、まずは書籍についてキーワード検索できるようにします。動作確認は、Windows 7、Excel 2010、VBA 7.0およびWindows XP、Excel 2007、VBA 6.5で行っています。

Excel VBAでWebサービス - 天気予報を取得してみよう
Excel VBAでWebサービス - MSNマネーから株価の推移を取得しよう
Excel VBAでWebサービス - Excelで書籍情報を検索・取得してみよう
Excel VBAでWebサービス - YouTube APIで動画を検索しよう
Excel VBAでWebサービス - ExcelでTwitterと連携する
Excel VBAでWebサービス - ExcelでTwitterと連携する2
Excel VBAでWebサービス - ExcelでTwitterと連携する 完成編

図1.完成サンプル

Amazonの商品検索について

Amazon Web Service(AWS)の商品検索サービスは、広告やアソシエイトと連携し、Product Advertising API(以降、PAAPIと省略)という形で提供されています。 PAAPI登録に当たっては、Amazonアカウントも必要です。未登録の場合は、AmazonのWebサイトから利用者登録してください。

PAAPIを利用するには、以下の2つの準備が必要です。

  1. PAAPIの開発者として登録する
  2. アソシエイト・プログラムに登録する

PAAPIの開発者として登録する

以下のURLからアクセスし、下記の表の手順に従って登録します。

 https://affiliate.amazon.co.jp/gp/advertising/api/detail/main.html

図2.PAAPI初期画面

表1.PAAPI登録手順

画面 操作
PAAPI初期画面 [アカウント作成]をクリック
PAAPI SIGN IN画面 利用者アカウントのEメールアドレスを入力、「I am a new customer.」をチェックし「Sign in ~」をクリック
Registration画面 必要事項を入力し「Create account」をクリック
PAAPI ACOUNT INFO画面 必要事項を入力し「Complete Registration」をクリック
PAAPI SUCCESS画面 「Manage Your Account」をクリック
PAAPI アカウントサービス画面 アクセスキー情報の枠内の[こちらのリンク]をクリック(図3)
Sign In or Create an AWS Account画面 Eメールアドレスを入力、「I am a returning user」をチェック、パスワードを入力し「Sign in ~」をクリック
セキュリティ証明書画面 下記、本文参照(図4)

図3.PAAPI アカウントサービス画面

図4.セキュリティ証明書画面

アクセスキーID(英数20文字)とシークレットアクセスキー(英数40文字)を控えておいてください。

アソシエイト・プログラムに登録する

以下のURLからアクセスし、下表の手順に従って登録します。

 https://affiliate.amazon.co.jp/

図5.Amazonアソシエイト初期画面

表2.アソシエイト・プログラム登録手順

画面 操作
Amazonアソシエイト初期画面 [無料アカウント作成]をクリック
Amazonアソシエイト-アカウント情報画面 必要な情報を入力し「次:Webサイト情報」をクリック
Amazonアソシエイト-Webサイト情報画面 必要事項を入力し[完了]をクリック

図6.Amazonアソシエイト-申し込み完了画面

アソシエイトID(英数字)を控えておいてください。

HTTP通信の手順

「Excel VBAでWebサービス - ExcelでTwitterと連携する2」の「OAuthによるHTTP通信の手順」とほぼ同じです。Amazonで異なる点は以下の通りです。

  1. フェーズは3のみ(トークンのやりとりは不要)
  2. 電子署名の方式はSHA256、暗号化キーは「シークレットアクセスキー」
  3. 引数の送信は、GET送信のクエリー文字列として追加

図7.HTTP通信の手順

リクエストの引数には表3のようなものがあります。

表3.リクエストの主な引数

引数名 設定値
AWSAccessKeyId (アクセスキーID)
AssociateTag (アソシエイトID)
Service 商品検索する場合、AWSECommerceService
Operation 商品検索では、ItemSearchを推奨
ResponseGroup 価格、発行日取得のため、ItemAttributesを指定
Timestamp アクセス日時
SearchIndex 商品種別「Books」
Sort ソート順(salesrank|pricerank|daterank)
Author 著者名
Title タイトル
Publisher 発行者
Keywords キーワード

Excelによる開発

Excel 2010を起動した後、以下の手順で行います。

  1. 各種の値を格納する名前を定義し、固定値と関数を設定する
  2. 操作画面用の名前、オブジェクトを設定する
  3. VBAに必要な参照設定を行う
  4. HTTP通信を行うVBAを記述する
  5. 商品検索を行う共通部分のVBAを記述する
  6. オブジェクトの処理に応じたVBAを記述する

各種の値を格納する名前を定義し、固定値と関数を設定する

まず、リクエストの共通引数と、レスポンスの状態を格納しておくため、シートの右の方に、以下の名前を定義し、固定値を設定しておきます。

図8.共通引数などの格納場所の準備

表4.共通引数などのセルの名前定義と設定値

セルの名前定義 設定値
access_key_id (アクセスキーID)
secret_access_key (シークレットアクセスキー)
associate_id (アソシエイトID)
service AWSECommerceService
operation ItemSearch
response_group ItemAttributes
host ecs.amazonaws.jp
path /onca/xml
url ="http://" & host & path (左式を設定)
OAuthStatus (初期設定は不要)

次に、リクエスト検索とレスポンス取得のため、以下のようにセルの名前定義と固定値の設定をしておきます。

図9.検索引数などの格納場所の準備

表5.検索引数などのためのセルの名前定義と設定値

セルの名前定義 説明 設定値(ワークシート関数)
SearchKeyTableJP 検索項目の表示名 著者、書名、出版社、キーワード
SearchKeyTable 検索項目の引数名 Author、Title、Publisher、Keywords
SortTypeTableJP ソート順の表示名 売れている順、価格の安い順、発行日の新しい順
SortType 選択したソート順 (コンボボックスで選択した値が入る)
SortTypeIndex ソート順のインデックス =MATCH(SortType,SortTypeTableJP,0)
SortTypeTable ソート順の引数名 salesrank、pricerank、daterank
ResItemTableJP 取得データ項目の表示名 著者/タイトル/出版社/標準価格/発行日
ResItemTable 取得データ項目のタグ名 Author/Title/Publisher/ListPrice/PublicationDate

操作画面用の名前、オブジェクトを設定する

以下のように検索画面を準備します。

図10.検索画面の準備

表6.セルの名前定義

セルの名前定義 説明
SearchValueList 条件の入力用(4行分)
TotalResults 結果の総件数
CurrentPage 結果の表示ページ
TotalPages 結果の総ページ数
ResValueTable 結果の詳細表示(10行固定)

図11.オブジェクトのプロパティ

コンボボックスでは、選択肢が格納されているセル範囲をListFillRangeプロパティに、選択された値を格納するセルをLinkedCellプロパティに設定します。 コマンドボタンのうち、[cbNext]と[cbPrev]のEnableプロパティはFalseに設定しておきます。

VBAに必要な参照設定を行う

[Alt]+[F11]キーでVBエディタを開き、メニューバーから[ツール]-[参照設定]をクリックし、「Microsoft XML, v3.0」と「Microsoft Scripting Runtime」を追加してください。

HTTP通信を行うVBAを記述する

「Excel VBAでWebサービス - ExcelでTwitterと連携する 2」の「OAuthによるHTTP通信を行うVBAを記述する」とほぼ同じです。Amazonで異なる点のみ説明します。

Timestamp引数では、現在日時から日本の時差9時間を引いたものを「YYYY-MM-DDTHH:mm:SSZ」形式で設定します。 電子署名の作成では、ベース文字列を(1)GET、(2)ecs.amazonaws.jp、(3)/onca/xml、(4)リクエスト引数、の4つを改行文字(vbLf)で繋げて作り、ユーザー定義関数hmac_sha256を使って電子署名を作成します。 引数は電子署名とともにクエリ引数としてURLに追加します。

 http://ecs.amazonaws.jp/onca/xml?引数名1=値1&・・・&引数名n=値n&Signature=(電子署名)

これをGETメソッドで送信します。

商品検索を行う共通部分のVBAを記述する

「Excel VBAでWebサービス - ExcelでTwitterと連携する 完成編」の「タイムラインを取得して表示するVBAの開発」とほぼ同じです。

Amazonで異なる点のみ説明します。

商品検索を行うVBA

Private Sub SearchItem(ByVal ItemPage As Integer)
    '要求ページをItemPage仮引数で受け取る
    '変数の準備(略)

    '(1)検索条件の入力チェック(略)

    '(2)引数の準備
    '連想配列オブジェクトの生成
    Set param = New Scripting.Dictionary

    '(2-1)商品種別をSearchIndex引数に設定する
    param("SearchIndex") = "Books"

    '(2-2)検索条件を引数に設定する
    For idxVal = 1 To Range("SearchValueList").Rows.Count
        If Len(Range("SearchValueList").Cells(idxVal)) > 0 Then
            param(Range("SearchKeyTable").Cells(idxVal, 1)) = Range("SearchValueList").Cells(idxVal)
        End If
    Next

    '(2-3)ソート順を引数に設定する
    param("Sort") = Range("SortTypeTable").Cells(Range("SortTypeIndex"), 1)

    '(2-4)表示ページを引数に指定する
    param("ItemPage") = ItemPage

    '(3)HTTP通信によるリクエスト送信(略)

    '(4)レスポンスの展開
    Set elmResponse = xmlRes.DocumentElement
    Set elmItems = elmResponse.SelectSingleNode("Items")

    '(4-1)検索件数、ページ数の取得
    Set elmRequest = elmItems.SelectSingleNode("Request")
    Set elmSearchRequest = elmRequest.SelectSingleNode("ItemSearchRequest")
    Set elmItemPage = elmSearchRequest.SelectSingleNode("ItemPage")
    Range("CurrentPage") = elmItemPage.Text
    Set elmTotalResults = elmItems.SelectSingleNode("TotalResults")
    Range("TotalResults") = elmTotalResults.Text
    Set elmTotalPages = elmItems.SelectSingleNode("TotalPages")
    Range("TotalPages") = elmTotalPages.Text

    '(4-2)検索結果データの展開
    Set elmItemList = elmItems.SelectNodes("Item")
    For idxItem = 0 To elmItemList.Length - 1
        'データ1件分の処理
        Set elmItem = elmItemList(idxItem)
        '詳細ページURLの取得
        Set elmItemUrl = elmItem.SelectSingleNode("DetailPageURL")
        txtUrl = elmItemUrl.Text
        ttlUrl = ""
        '(4-3)属性タグの取得
        Set elmItemAttrTag = elmItem.SelectSingleNode("ItemAttributes")
        For idxTag = 0 To elmItemAttrTag.ChildNodes.Length - 1
            '(4-4)属性タグ内の処理
            txtTag = elmItemAttrTag.ChildNodes(idxTag).nodeName
            For idxCol = 1 To Range("ResItemTable").Columns.Count
                '(4-5)必要な取得項目ごとの処理
                txtCol = Range("ResItemTable").Cells(1, idxCol)
                If txtCol = "Title" Then idxUrl = idxCol
                If txtTag = txtCol Then
                    '(4-6)タグと取得項目が一致した場合
                    If txtCol = "ListPrice" Then
                        '(4-7)価格の場合は、子要素のFormattedPriceタグの値を取得する
                        txtVal = elmItemAttrTag.ChildNodes(idxTag).SelectSingleNode("FormattedPrice").Text
                    Else
                        txtVal = elmItemAttrTag.ChildNodes(idxTag).Text
                    End If
                    If txtCol = "Title" Then
                        '(4-8)タイトルの場合は、いったん変数へ格納
                        'タグが既出の場合、カンマで続ける
                        ttlUrl = IIf(ttlUrl = "", txtVal, ttlUrl & "," & txtVal)
                    Else
                        txtDat = Range("ResValueTable").Cells(idxItem + 1, idxCol)
                        'タグが既出の場合、カンマで続ける
                        Range("ResValueTable").Cells(idxItem + 1, idxCol) = IIf(txtDat = "", txtVal, txtDat & "," & txtVal)
                    End If
                End If
            Next
            '(4-9)詳細ページURLをタイトルに貼る
            ActiveSheet.Hyperlinks.Add _
                anchor:=Range("ResValueTable").Cells(idxItem + 1, idxUrl), _
                Address:=txtUrl, TextToDisplay:=ttlUrl 'リンク付きのタイトル
        Next
    Next

    '(5)次の10件、前の10件ボタンの利用可否を設定
    cbPrev.Enabled = (Range("CurrentPage") > 1)
    cbNext.Enabled = (Range("CurrentPage") < Range("TotalPages"))

 End Sub

(2-2)では、検索4条件を走査し、例えば「書名」に"Excel"と入力されていれば、param("Title")="Excel"と引数を追加します。 (2-3)では、例えば「価格の安い順」が選ばれていれば、param("Sort") = "pricerank"と引数を設定します。

(4)でXMLデータを展開します。

図12.レスポンスXMLデータの構造

(4-1)では、検索件数とページ数を取得し、対応セルに転記しています。(4-2)からはidxItem変数を使って、商品データ1件ごとの走査を行います。詳細ページのURLは、後でタイトルにリンクさせるため、txtUrlに格納し、タイトルを格納する変数ttlUrlをクリアしておきます。

図13.商品データ1件ごとの走査

(4-3)で属性タグを取得し、その子要素すべてについてidxTag変数を使って走査します。これは、取得項目の要素が存在しない場合、複数存在する場合があり、SelectSingleNodeメソッドでピンポイントに取得できるとは限らないためです。(4-4)では、子要素のタグ名をtxtTagに格納し、取得項目をidxCol変数で、1列ずつ走査しています。

(4-5)では、取得項目名をtxtColに格納しています。これがTitleだった場合は、後でURLのリンクを設定するため、該当する列番号をidxUrlに格納しておきます。タグと取得項目が一致した場合、(4-6)以下の処理を行います。

(4-7)ではタグがListPriceの場合は子要素のFormattedPriceタグの値を、それ以外の場合は子要素の値を、txtVal変数に格納します。(4-8)ではタグがTitleの場合は、いったんttlUrl変数に格納し、それ以外の場合はResValueTableセル範囲のしかるべき行、列に直接格納します。いずれの場合も、格納済みの場合は、2番目以降の出現と見て、カンマで繋げるようにします。

(4-9)では、txtUrlとttlUrlに格納しておいた、リンク先URLとタイトル文字列を使って、ResValueTableセル範囲のしかるべき行、列にハイパーリンクを設定しています。

データの展開が終わったら、(5)で現在のページを1と比較し[前の10件]ボタンを有効/無効を設定します。また、総ページ数と比較し、[次の10件]ボタンの有効/無効を設定します。

オブジェクトの処理に応じたVBAを記述する

ワークシートに戻り、[開発]タブの[デザインモード]をONの状態で、各種オブジェクトをダブルクリックして開く、VBエディタで以下のイベントプロシージャを記述します(リストは省略)。

表7.イベントプロシージャ一覧

イベント プロシージャ名 仮引数値 処理内容
[検索する]クリック時 cbSearch_Click() 1 1ページ目のデータを取得する
[次の10件]クリック時 cbNext_Click() 現在ページ + 1 次のページのデータを取得する
[前の10件]クリック時 cbPrev_Click() 現在ページ - 1 前のページのデータを取得する

これにて完成です。検索条件を入力し、ソート順を選んで、[検索する]ボタンをクリックしてみてください。10件ずつ取得でき、タイトルのリンクをクリックすると、書籍の詳細ページが表示されれば成功です。

まとめ

Amazonの書籍検索はいかがでしたか。取扱商品は他にも多数あります。次回は、商品種別を切り替えて、検索できる方法を説明します。お楽しみに。

WINGSプロジェクト 遠藤 存著/山田祥寛監修
WINGS プロジェクトについて
テクニカル執筆プロジェクト(代表山田祥寛)。海外記事の翻訳から、主にWeb開発分野の書籍・雑誌/Web記事の執筆、講演等を幅広く手がける。2011年5月時点での登録メンバは35名で、現在も一緒に執筆をできる有志を募集中。