2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】Yahoo!ショッピングAPI備忘録

Last updated at Posted at 2023-08-17

YahooはYJDN(Yahoo! JAPAN Developer Network)という名前でWeb APIを提供しており、YID連携(ログイン認証)が必要なものとそうでないものがある。

  • YID連携必要 - ストア運営のサポート API
  • YID連携不要 - ショッピング情報取得 API

今回は、ストア情報の取得・更新ができるYID連携が必要なAPIの利用の方法を紹介する。

ストアクリエイタプロ3.PNG

事前準備

下記公式サイトを参照して、準備する。

  1. Yahoo! JAPAN IDを取得する。
  2. アプリケーションを登録する。
    • ID連携利用有無 = ID連携を利用する
    • アプリケーションの種類 = サーバーサイド(Yahoo! ID連携 v2)
    • 個人情報提供先としてユーザーへ開示することに同意しますか? = 同意しない
    • どちらの用途で発行しますか? = 本番環境用
    • ストアURL = https://www.yahoo.co.jp/
      YahooApplication1.PNG
      YahooApplication2.PNG
      YahooApplication3.PNG
      YahooApplication4.PNG
      ストアクリエイタプロ2.PNG
  3. アプリケーションの管理を開き、編集ボタンを押して、以下の欄にURLを記載する
    コールバックURL = ツールごとに決められたURL
    例) https://www.yahoo.co.jp/
  4. 従業員登録されているビジネスIDとの紐づける
    これらの Yahoo!ID に紐づくビジネス ID を、ストアクリエイタ Pro の権限管理設定に登録する
    ストアクリエイタ Pro に「ツール管理権限(Yahoo!ビジネスマネージャー)」を持っているYahoo! JAPANビジネスIDでログインする
    設定->権限管理設定を押し、編集を押す
    Yahoo! JAPANビジネスIDと氏名、権限管理種別を追加する
    ストアクリエイタプロ1.PNG

API認証

  1. 下記コードを実行して、認可Code取得に必要なURLを取得する。client_idには上記手順で取得したClient IDを用いる。
    # Authorizationエンドポイントへリダイレクト
    client_id = *******************
    url = 'https://auth.login.yahoo.co.jp/yconnect/v2/authorization'
    params = {}
    params ['response_type'] = 'code'
    params ['client_id'] = client_id
    params ['redirect_uri'] = 'https://www.yahoo.co.jp/'
    params ['scope'] = 'openid'
    response = requests.get(url, params)
    print(response.url)
    
  2. 表示されたURLをブラウザで開き、ログイン&二段階認証する
  3. リダイレクト後のURL末尾のcode=***の認可codeをコピーする
  4. 下記コードを実行して、アクセストークンとリフレッシュトークンを取得する。auth_codeには取得した認可codeを、secret_keyには上記手順で取得したシークレットを用いる。
    #上記のURLへブラウザでアクセスして、二段階認証をすると、リダイレクト先のURLに認可codeが得られる
    auth_code = *******
    secret_key = *******************
    url = 'https://auth.login.yahoo.co.jp/yconnect/v2/token'
    
    string_to_encode = client_id + ':' + secret_key
    encoded_string = base64.b64encode(string_to_encode.encode("utf-8")).decode("utf-8")
    
    params = {}
    params ['client_id'] = client_id
    params ['client_secret'] = secret_key
    params ['code'] = auth_code
    params ['grant_type'] = 'authorization_code'
    params ['redirect_uri'] = 'https://www.yahoo.co.jp/'
    headers = {}
    headers ['Authorization'] = 'Basic ' + encoded_string
    response = requests.post(url,params,headers=headers)
    results = response.json()
    if 'access_token' in results.keys():
        print('Correctly Get Access Token & Refresh Token!')
        access_token = results['access_token']
        refresh_token = results['refresh_token']
        print(results['access_token'], '\n')
        print(results['refresh_token'], '\n')
    else:
        print('Error Access Token & Refresh Token...')
        print(results)
    
  5. リフレッシュトークンでアクセストークンを更新する。
    # リフレッシュトークンは、12時間制限 -> 公開鍵を使えば、4週間に伸びる
    access_token = ********************
    refresh_token = ********************
    
    url = 'https://auth.login.yahoo.co.jp/yconnect/v2/token'
    string_to_encode = client_id + ':' + secret_key
    encoded_string = base64.b64encode(string_to_encode.encode("utf-8")).decode("utf-8")
    params = {}
    params ['refresh_token'] = refresh_token
    params ['grant_type'] = 'refresh_token'
    headers = {}
    headers ['Content-Type'] = 'application/x-www-form-urlencoded'
    headers ['Authorization'] = 'Basic ' + encoded_string
    response = requests.post(url,params, headers=headers)
    results = response.json()
    access_token = results['access_token']
    print(access_token)
    

ここで取得したアクセストークンを用いて各APIを実行する。

各API実行

下記公式サイトを参照して、実行する。

1.ストアアカウントの在庫情報取得(アイテムコードを指定)

アイテムコード(ショップで一意の商品コード)を指定して在庫情報を取得する

item_code = *********
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getStock"

params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = item_code

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

response = requests.post(YahooAPIURL, data=params, headers=headers)
print(response.status_code)
print(response.text)

2. ストアアカウントの全在庫情報取得

ストアアカウントが保有する全ての商品・在庫・ストアカテゴリーの情報を取得する。

target_type = 1
# 1 : 商品データ
# 2 : 在庫データ
# 3 : ストアカテゴリ
YahooAPIURL_request = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadRequest"
YahooAPIURL_check = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadList?seller_id={}".format(seller_id)
YahooAPIURL_download = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadSubmit?seller_id={}&type={}".format(seller_id, target_type)

params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['type'] = target_type

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

response = requests.post(YahooAPIURL_request, data=params, headers=headers)
print(response.status_code)
print(response.text)
response = requests.get(YahooAPIURL_check, headers=headers)
print(response.status_code)
print(response.text)
response = requests.get(YahooAPIURL_download, headers=headers)
print(response.status_code)

escaped_string = response.text.replace('\n', r'\n')
pattern = r'"(.*?)"'
quoted_strings = re.findall(pattern, escaped_string)
lines = [re.split(r'(?<!\\)\n', quoted_string)[0] for quoted_string in quoted_strings]
sl = 64
lines = [lines[elem*sl : elem*sl + sl] for elem in range(int(len(lines)/sl))]
print(lines)

f = open('ProductList.csv', 'w')
for item in lines:
    f.write(','.join(item) + '\n')

3. ストアアカウントの全在庫情報取得

ストアアカウントの全商品の指定した情報を取得する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getRealStock?sellerId={}".format(seller_id)

params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['type'] = target_type

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)

4. 店舗情報取得

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getRealStore?sellerId={}".format(seller_id)

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)

5. 画像一覧取得

ストアアカウントが保有する全てのアップロードした画像を取得する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/itemImageList?seller_id={}&query=&start=1&results=100".format(seller_id)

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)

import xml.etree.ElementTree as ET 
root = ET.fromstring(response.text)
print(f"root.tag={root.tag} .attrib={root.attrib}")
image_dict = {}
for child in root:
    image_dict[child.find("Name").text] = child.find("Url").find("ModeI").text
    print(child.find("Name").text, child.find("Url").find("ModeI").text)
print(image_dict)

6. カテゴリID取得

指定した商品カテゴリーIDの子カテゴリーのカテゴリー名とIDを一覧で取得する。

YahooItemSearchURL = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/categorySearch"
params = {}
params ['appid'] = client_id
params ['category_id'] = 1
response = requests.get(YahooItemSearchURL,params)
print(response.status_code)
res = json.loads(response.text)
print(list(res['ResultSet']['0']['Result']['Categories']['Children'].keys()))
for index in list(res['ResultSet']['0']['Result']['Categories']['Children'].keys()):
    if index.isdecimal():
        item = res['ResultSet']['0']['Result']['Categories']['Children'][index]
        print('%s,%s'%(item['Id'],item['Title']))

YahooItemSearchURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getShopCategory?seller_id={}".format(seller_id)
response = requests.get(YahooItemSearchURL, headers=headers)
print(response.status_code)
print(response.text)
root = ET.fromstring(response.text)
print(f"root.tag={root.tag} .attrib={root.attrib}")
image_dict = {}
for child in root:
    print(child.find("CategoryCode").text, child.find("CategoryName").text)

7. 商品登録

1つの商品をストアアカウントへ商品登録する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/editItem"

headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}

params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01' # 商品コード
params['path'] = 'Category01' # ストアカテゴリのパス
params['name'] = 'sample product' # 商品名
params['product_category'] = 2505 # YahooショッピングカテゴリID
params['original_price'] = 100000 # 定価
params['price'] = 100000 # 通常販売価格
params['lead_time_instock'] = 2000 # 発送日情報管理番号(在庫があり時)
params['lead_time_outstock'] = 4000 # 発送日情報管理番号(在庫が切れ時)
params['postage_set'] = 1 # 商品に紐づく配送グループ管理番号

response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)

8. 商品削除

1つの商品をストアアカウントから削除する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/deleteItem"
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01'
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)

9. カテゴリーリスト

ストアアカウントの全てのストアカテゴリーを一覧で取得する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/stCategoryList?seller_id={}".format(seller_id)
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<PageKey>(.*?)</PageKey>'
stcat_keys = re.findall(pattern, escaped_string)
print(stcat_keys)
pattern = r'<Name><!\[CDATA\[(.*?)\]\]></Name>'
Name_keys = re.findall(pattern, escaped_string)
print(Name_keys)

10. 商品リスト

指定したストアカテゴリーの全ての商品情報を取得する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/myItemList?seller_id={}&start=1&results=100&stcat_key={}".format(seller_id,stcat_keys[1])

response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Name><!\[CDATA\[(.*?)\]\]></Name>'
ProductName_keys = re.findall(pattern, escaped_string)
print(ProductName_keys)
pattern = r'<ItemCode>(.*?)</ItemCode>'
ItemCode_keys = re.findall(pattern, escaped_string)
print(ItemCode_keys)

11. データチェック履歴一覧API V2

ストアに反映されていないデータを、商品・在庫・画像などの情報を指定して取得する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V2/dataCheckHistorySummary?seller_id={}&offset=0&limit=100&dataType=STOCK".format(seller_id)
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)

12. データチェック履歴一覧API V2

反映されていないデータを全て取得する。

# publish_id=0で未反映項目のみ
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/publishHistorySummary?seller_id={}&publish_id=0&start=1&results=100".format(seller_id)
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<PublishId>(.*?)</PublishId>'
PublishId_keys = re.findall(pattern, escaped_string)
print(PublishId_keys)
pattern = r'<ItemPageNum>(.*?)</ItemPageNum>'
ItemPageNum_keys = re.findall(pattern, escaped_string)
print(ItemPageNum_keys)
pattern = r'<CategoryPageNum>(.*?)</CategoryPageNum>'
CategoryPageNum_keys = re.findall(pattern, escaped_string)
print(CategoryPageNum_keys)

13. 全反映予約

反映されていないデータをすぐに全て反映する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/reservePublish"
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['mode'] = 1

response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Status>(.*?)</Status>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)

14. 在庫更新API

指定したアイテムコードの在庫情報を更新する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/setStock"
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
    'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01'
params['quantity'] = 1
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)

15. 画像アップロードAPI

画像をアップロードする。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/uploadItemImage?seller_id={}".format(seller_id)
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
}
params = {}
params['appid'] = client_id
files = {'file': ('code01.jpg', open('code01.jpg', 'rb'))}

response = requests.post(YahooAPIURL, headers=headers, files=files, data=params)
print(response.status_code)
print(response.text)

16. SHPカテゴリ検索API

指定した検索キーワードから商品カテゴリーを推測する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getShopCategoryList?seller_id={}&query=PC&category=2498".format(seller_id)
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<CategoryCode>(.*?)</CategoryCode>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)

17. 価格更新API

指定したアイテムコードの価格情報を更新する。

YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/updateItems"
headers = {
    'Host': 'circus.shopping.yahooapis.jp',
    'Authorization': 'Bearer ' +  access_token,
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item1'] = 'item_code=code01&price=10000&sale_price='.encode('utf-8')

response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Status>(.*?)</Status>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)

公開鍵の取得・使用方法

公開鍵なしでは下記APIは発行から12時間しかアクセストークンが有効ではない。

  • 注文検索API
  • 注文詳細API
  • 注文内容変更API
  • メッセージ投稿API
  • 質問詳細API
  • 質問一覧API
  • 定期購入親注文詳細取得API
  • 定期購入情報変更API
  • 定期購入情報変更履歴詳細API

公開鍵を使用することで、これを4週間まで延ばすことができる。
公開鍵認証は、Yahoo! ショッピング出店ストアのみ申請が可能。
発行した月より「1年間」有効。

下記リンクから取得することができる。

公開鍵を用いたリクエスト

import time
import base64
import requests
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

# 設定
seller_id = "{ストアアカウント}"
public_key_path = "./public.key"  # 公開鍵のパス (例: "C:\\Users\\store\\public.key")
key_version = "1"  # 公開鍵のバージョン
access_token = "{アクセストークン}"  # アクセストークン
api_url = "{APIのURL}"  # APIのURL

# 認証情報作成
authentication_value = f"{seller_id}:{int(time.time())}"

# 公開鍵の読み込み
with open(public_key_path, 'r') as f:
    public_key = RSA.import_key(f.read())

# 認証情報の暗号化
cipher = PKCS1_v1_5.new(public_key)
encrypted_authentication_value = cipher.encrypt(authentication_value.encode('utf-8'))

# 認証情報のBase64エンコード
encoded_authentication_value = base64.b64encode(encrypted_authentication_value).decode('utf-8')

# リクエストヘッダーの設定
request_headers = {
    "Authorization": f"Bearer {access_token}",
    "X-sws-signature": encoded_authentication_value,
    "X-sws-signature-version": key_version
}

# HTTP通信実行
response = requests.get(api_url, headers=request_headers)

# 結果表示
print(response.text)

参考文献

2
6
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
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?