46bi_ru
@46bi_ru

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Python質問】Yahoo!のAPI ID連携 について

解決したいこと

Yahoo!のAPIについて

初心者です。
pythonを利用して、ヤフーのID連携を行おうとしています。
ログイン画面までは到達したのですが、認可コードを取得するところで止まっています。

■やりたいこと
「Yahoo! ID連携に対応したAPIを利用したいため、認可コードを取得したい。」
流れとしては下記。
①クライアントIDとシークレットでauthorizationアクセス
②ログインして認可コードをもらう
③認可コードを使って、アクセストークンをもらう

発生している問題・エラー

認可コード s://auth.login.yahoo.co.jp/yconnect/v2/consent?session=lHGzBsWt&display=page&.scrumb=urAJ186NOzk&bcrumb=dD1oOWRpaUImc2s9TnluOFVXWmpIUVgzNWZVYTBRRG5DemZVeWtjLQ%3D%3D
status:error 400

本来、「認可コード XXXXX」のように認可コードが取得できるのですが
エラーが発生しています。
原因を調べていたのですが、わからずご教示いただたいです。
Pythonに関しての知識はほとんどなく、調べながら行っています。
初歩的なことが原因かもしれませんが、どうぞよろしくお願いいたします。

ソースコード

import time
import codecs
import os
import re

import pandas as pd

import requests, base64
import xml.etree.ElementTree as ET
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager


# Yahoo API 向け設定
seller_id = "ストアのID"  

yid = "ヤフーのID"
ypass = "ヤフーのパスワード"

client_id = "発行したアプリケーションID"
client_secret = "発行したシークレットID"

redirect_uri = "https://shoppingXXXXXXXXXX"

# YahooのAPIアクセストークンを取得する関数
def Yahoo_get_token():

    url = "https://auth.login.yahoo.co.jp/yconnect/v2/authorization"

    params = {
        "response_type": "code",
        "client_id": client_id,
        "redirect_uri": redirect_uri,
        "scope": "openid address profile email",
        "bail": 1
    }

    res = requests.get(url, params=params)
    time.sleep(1)

    options = webdriver.ChromeOptions()
    # options.add_argument('--headless')
    driver = webdriver.Chrome(ChromeDriverManager(
        log_level=0, print_first_line=False).install(), options=options)
    driver.get(res.url)
    time.sleep(1)

    # ログイン処理
    driver.find_element_by_name("login").send_keys(yid)
    driver.find_element_by_name("btnNext").click()
    time.sleep(1)

    driver.find_element_by_name("passwd").send_keys(ypass)
    driver.find_element_by_name("btnSubmit").click()
    time.sleep(1)

    # 認可コード
    start = driver.current_url.find("code=") + 5
    Length = len(driver.current_url)
    code = driver.current_url[start:Length]

    print("認可コード", code)

    # selenium終了
    driver.close()
    driver.quit()

    # アクセストークン
    url = "https://auth.login.yahoo.co.jp/yconnect/v2/token"

    data = {
        "grant_type": "authorization_code",
        "redirect_uri": redirect_uri,
        "code": code,
    }

    base64_id_secret = client_id + ':' + client_secret
    base64_id_secret_byte = base64.b64encode(base64_id_secret.encode('utf-8'))
    auth_header = 'Basic ' + base64_id_secret_byte.decode('ascii')

    headers = {
        'HTTP-Version': 'HTTP/1.1',
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
        'Authorization': auth_header
    }

    res = requests.post(url, data=data, headers=headers)

    if res.status_code == 200:
        res_json = res.json()
        access_token = res_json["access_token"]
        refresh_token = res_json["refresh_token"]

        return res.status_code, [access_token, refresh_token]
    else:
        return res.status_code, []

# 指定された商品の商品情報を返します。
# https://developer.yahoo.co.jp/webapi/shopping/getItem.html
def API_item_get(token, item_code):
    endpoint = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getItem"

    params = {
        'seller_id': seller_id,
        'item_code': item_code
    }

    headers = {
        'HTTP-Version': 'HTTP/1.1',
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
        'Authorization': 'Bearer ' + token,
    }

    res = requests.get(endpoint, params=params, headers=headers)
    xml = res.text
    return xml

def API_item_category(token):
    endpoint = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/stCategoryList"

    params = {
        'seller_id' : seller_id,
        # "page_key": page_key
    }

    headers = {
        'HTTP-Version': 'HTTP/1.1',
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
        'Authorization': 'Bearer ' + token,
    }

    res = requests.get(endpoint, params=params, headers=headers)
    xml = res.text

    return xml

def save_csv(df, dir_path, filename):
    os.makedirs(dir_path, exist_ok=True)
    with codecs.open(os.path.join(dir_path, filename), 'w', 'shift_jisx0213', 'ignore') as f:
        df.to_csv(f, index=False)

def xml2df(xml_data):
    root = ET.XML(xml_data) # element tree
    all_records = []
    for i, child in enumerate(root):
        record = {}
        for subchild in child:
            record[subchild.tag] = subchild.text
        all_records.append(record)
    df = pd.DataFrame(all_records)
    return df

def test():
    # Yahoo APIアクセストークン取得
    status, token = Yahoo_get_token()

    # 正常に取得できた場合以下実行
    if status == 200:
        xml = API_item_category(token[0])
        df = xml2df(xml)

        save_csv(df, "./", "output.csv")
    else:
        print("status:error", status)
test()
2

1Answer

driver.current_urlが期待値かどうか(code=が含まれていることを期待しているようですが)の確認はできていますか?

1Like

Comments

  1. @46bi_ru

    Questioner

    確認が遅くなり大変申し訳ございません!

    下記記述の前に「time.sleep(20)」を追加することで解決いたしました。

    python
    driver.close()
    driver.quit()

Your answer might help someone💌