LoginSignup
8
14

More than 3 years have passed since last update.

Amazon MWS を使ってASINから商品情報を取得するPythonコード

Posted at

今回はMWSのAPIを使ってAmazonの現在価格やランキングなどの商品情報を取得します。プログラミング言語はPythonを使います。今回から何回かに分けてネットショップの運営に役立つツールを紹介します。

このプログラムで取得できる情報

  • 現在価格
  • 現在のランキング
  • 新品出品者数
  • 中古出品者数

注意点!

  • 検索には10桁のASINもしくは書籍に使われているISBN-10で使います。(JANコードなどからは次回以降に紹介します)
  • アマゾンのアソシエイトのAPIとは別物です。
  • MWSを利用するには大口出品者(有料サービス)になる必要があります。

必要になる情報

  • SELLER_ID
  • ACCESS_KEY_ID
  • ACCESS_SECRET
  • MarketplaceId

*上記の開発者IDを手に入れるのに大口出品者になる必要があります。
APIの仕様はこちらから
http://docs.developer.amazonservices.com/ja_JP/dev_guide/index.html

実際のコード

コードが汚いのは目をつぶって下さい。

get_dataという関数に検索したいASINもしくはISBN-10の文字列を引数として渡します。
入力 "4873117380"
出力 {ASIN: [現在価格, ランキング, '新品出品者数', '中古出品者数']}

Pythonのコード
import base64
import datetime
import hashlib
import hmac
import pprint
import requests
import six
import urllib.parse

from bs4 import BeautifulSoup

# この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。

AMAZON_CREDENTIAL = {
    'SELLER_ID': 'Your SELLER_ID',
    'ACCESS_KEY_ID': 'Your ACCESS_KEY_ID',
    'ACCESS_SECRET': 'Your ACCESS_SECRET',
    'MarketplaceId': 'Your MarketplaceId',
    }
DOMAIN = 'mws.amazonservices.jp'
ENDPOINT = '/Products/2011-10-01'

# この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。この部分を書き換えて下さい。


def get_data(search_code):
    timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
    data = {
        'AWSAccessKeyId': AMAZON_CREDENTIAL['ACCESS_KEY_ID'],
        'Action': 'GetCompetitivePricingForASIN',
        'SellerId': AMAZON_CREDENTIAL['SELLER_ID'],
        'SignatureMethod': 'HmacSHA256',
        'MarketplaceId': AMAZON_CREDENTIAL['MarketplaceId'],
        'SignatureVersion': '2',
        'Timestamp': timestamp,
        'Version': '2011-10-01',
        'ItemCondition': 'NEW',
        'ExcludeMe': 'true',
        'ASINList.ASIN.1': search_code
    }

    query_list = list()
    for k, v in sorted(data.items()):
        query_list.append('{}={}'.format(k, urllib.parse.quote(v, safe='')))
    query_string = "&".join(query_list)

    canonical = "{}\n{}\n{}\n{}".format(
        'POST', DOMAIN, ENDPOINT, query_string
    )

    h = hmac.new(
        six.b(AMAZON_CREDENTIAL['ACCESS_SECRET']),
        six.b(canonical), hashlib.sha256)

    signature = urllib.parse.quote(base64.b64encode(h.digest()), safe='')

    url = 'https://{}{}?{}&Signature={}'.format(
        DOMAIN, ENDPOINT, query_string, signature)

    response = requests.post(url)
    soup = BeautifulSoup(response.content.decode(), "lxml")
    # print(soup.prettify())

    items = soup.find_all('asin')
    result_dict = dict()

    try:
        item_data = soup.find('getcompetitivepricingforasinresult', asin=search_code)
        # print('item_data', item_data)

        # asinを取得
        try:
            result_asin = item_data.asin.text
        except Exception as err_asin:
            print(err_asin)
            result_asin = 'ASINを取得できませんでした'

        # 価格を取得
        try:
            result_price = int(round(float(item_data.amount.text)))
        except Exception as err_price:
            print(err_price)
            result_price = '価格を取得できませんでした'

        # ランクを取得
        try:
            result_rank = int(item_data.rank.text)
        except Exception as err_rank:
            print(err_rank)
            result_rank = 'ランクを取得できませんでした'

        # 新品出品者数を取得
        try:
            # result_offerlisting_new = soup.offerlistingcount
            result_offerlisting_new = item_data.find('offerlistingcount', condition='New').text
            # print('result_offerlisting', result_offerlisting_new)
        except Exception as err_result_offerlisting_new:
            print(result_offerlisting_new)
            result_offerlisting_new = '新品出品者数を取得できませんでした'

        # 中古出品者数を取得
        try:
            result_offerlisting_used = item_data.find('offerlistingcount', condition='Used').text
            # print('result_offerlisting_used', result_offerlisting_used)
        except Exception as err_result_offerlisting_used:
            # print(err_result_offerlisting_used)
            result_offerlisting_used = '中古出品者数を取得できませんでした'

        result_dict['{}'.format(result_asin)] = [result_price, result_rank, result_offerlisting_new, result_offerlisting_used]

    except Exception as err_item:
        # print(err_test)
        result_test = 'itemを取得できませんでした'

    return result_dict


if __name__ == '__main__':
    print(get_data("4873117380"))

上のコードの、下記項目を自分のMWSの情報に書き換えて下さい。

  • Your SELLER_ID
  • Your ACCESS_KEY_ID
  • Your ACCESS_SECRET
  • Your MarketplaceId

上記のコードはISBN-10で4873117380を検索していてオライリーの入門Python3のデータを取ってきます。
{'4873117380': [3956, 3621, '4', '23']}
こんな感じで返ってくれば成功です。記事を書いている現在の価格は3956円だとわかります。

別の商品を検索したい場合は

if __name__ == '__main__':
    # この部分を書き換えて下さい。この部分を書き換えて下さい。
    print(get_data("検索したい ISBN-10 か ASIN"))

おわりに

ここまで見ていただきありがとうございます。見てくださった誰かのお役に立てれば幸いです。もっと効率の良い方法などは探せばたくさん見つかると思います。私もわからないところは検索して継ぎ接ぎでコードを書いております。結構前に書いたので引用はわからなくなってしまっています。申し訳ありません。

次回以降の話

取得できるデータは上記のものだけではありません。一部データをピックアップして取得しました。絞ったんですけど、かなり長くなってしまいましたので、連続してデータを取得する場合や、JAN/EAN/UPCコードから取得する方法など次回以降に投稿したいと思います。

8
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
14