PythonでBASEのAPIを叩いて商品データを取得してみる -その1-


某クラウドソーシングサイトで最近BASE関連の作業依頼をよく見かける気がします。(気のせいかもしれない)

私もたまーに案件を受けていたりしたのですが、BASEは商品データの取り扱いがとにかく不便!

CSVを利用した一括出品には対応しているものの、なぜか一括編集や一括削除ができないので一品一品修正したりする必要があるし、一括出品時も商品画像は最大5点までしか設定できない謎仕様!(商品編集画面からは最大20枚まで設定可能)

面倒臭すぎる・・・と思っていましたが、実はその辺の処理は全てAPI側で実装されているんですよね。

 「API叩く処理作るのもなぁ-・・・CSVとブラウザ自動操作で一応何とかなるし」

と、ずっと思っていたのですが、最近Pythonの勉強を始めた事もあり、勉強がてらついでにBASEのAPI用の処理も作ってみよう。

と言う事で、今回触ってみる事にしました。

今回作成する処理は各トークンの取得(後々説明します)~商品一覧データの取得まで。

ちなみにBASEって何?という方はこちらを参照↓

BASE (ベイス) | ネットショップを無料で簡単に作成(https://thebase.in/)

要は個人でも簡単にネットショップを開設できるサービスです。

後、初Pythonなので書き方とかはイマイチです。

その辺は指摘してもらえると嬉しいかも。

スポンサーリンク

BASEの準備

まずAPIを叩くには、BASEから「アクセスしても良いですよ」って許可をもらわないといけません。

という事でまずはBASEにログイン後、Developers画面から「アプリケーション」、「新規作成」の順で選択します。

続いてアプリ作成にあたって必要事項を入力する必要があるため、それぞれ必須項目を入力していきます。(以下例)

  • アプリ名:適当でOK
  • アプリの説明:適当でOK
  • アプリのURL:適当でOK(BASEの自店舗URLとか)
  • コールバックURL:↑(アプリのURL)と同じでOK
  • 利用権限:「商品情報を見る」にチェックを入れておきましょう
  • 検索APIの利用:一応チェックを入れておきます自ショップのデータを取得するだけの場合は、このチェックが入っていると申請が通らない様です。チェックは外しておきましょう

この下に更に「開発者情報」の入力欄が続きますが、ここは自分自身の情報を入力しておけば問題ありません。

以上、必要事項を全て入力後し終わったら申請を行います。

申請が通ったらもう一度Developersにアクセスし、「アプリケーション」、「一覧」と選択します。

すると一覧画面上に申請したアプリケーションが表示されていますので、選択してアプリの情報を確認します。

アプリ情報画面では「client_id」と「client_secret」という値が表示されています。この値はAPIを利用する際に必要となりますので、コールバックURLとあわせて保存しておきましょう。※何度でも確認出来るので、必要になったら見に来ればOK

以上でBASE側の作業は終了です。

認可コードを取得する

ここからPythonで処理を組んで行きますが、まずはアプリケーションの申請からAPIを使用するまでの流れを確認しましょう。

上の図を見て頂くと分かる通り、実際にAPIを使用してデータを要求できる様になるまでは全部で3つの作業を行う必要があります。

この内ステップ1は、先ほどBASE上で行ったアプリケーション申請に該当します。

そしてこのステップ1については初回のみの手順となるので、これ以降は必要ありません。
※現在のアプリは「商品情報取得」のみで申請しているので、「商品編集」を行いたい場合は別途申請が必要。

しかしステップ2とステップ3の処理については今後繰り返し行う必要があります。

なぜかと言うと、このステップで取得できる「認可コード」、「アクセストークン」、「リフレッシュトークン」にはそれぞれ有効期限が存在するためです。

認可コードを使用して「アクセストークン」、「リフレッシュトークン」と呼ばれるトークンを発行しますが、APIを利用する際に送信しなければいけない情報はこの内「アクセストークン」だけです。

しかしこのアクセストークンは発行から1時間程度で使用不可となるため、時間を空けてAPIを使おうとする度に再発行しなければいけません。

じゃあもう一度認可コードからアクセストークンを発行すれば・・・と考えると思いますが、この認可コードも1時間程度で使用不可となるので、こちらの方も取り直しが必要になります。

そこで、もっと簡単にアクセストークンを発行できないかと言うことで用意されているのが「リフレッシュトークン」です。

実はアクセストークンは、「認可コード」と「リフレッシュトークン」のどちらからでも発行する事が可能です。そしてリフレッシュトークンは有効期限が30日もあるため、暫くは更新の必要がありませんし、「認可コードからアクセストークンを発行する」という手順よりも簡単にアクセストークンを発行する事ができます。(手順については後述)

という事で、今回は「認可コードの取得」、「認可コードからアクセストークン(とリフレッシュトークン)の取得」、「リフレッシュトークンからアクセストークンの取得」という3種類の処理を実装していきます。

ではまずは「認可コードの取得」の処理から。

細かい部分は省略していくので、詳細についてはBASEが公開しているGitページを確認して下さい。

BASE API v1 ドキュメント (β版)

認可コードの取得について記述されているのはこちらのページですね。

GET /1/oauth/authorize

手順は以下の通り。

  1. クライアント側でこのURLへユーザーを遷移させるリンクを作成してください。
  2. ユーザーがBASE側へ遷移すると認証画面が表示されます。
  3. ユーザーがクライアントとの連携を許可した場合、コールバックURLに認可コードを付与してリダイレクトさせます。

URLを作成してそこにアクセスしろという事なので、リクエストパラメーターとURLの例を参考に処理を組みます。

[URLの例]

https://api.thebase.in/1/oauth/authorize?
response_type=code&
client_id=abc123&
redirect_uri=http%3A%2F%2Fhogehoge.com%2Fcallback.php&
scope=read_users%20read_orders&
state=hogehoge

リクエストパラメータは全部で5つ(青文字部分)。

各パラメータ名の後にある「=」の後に値をセットし、それぞれ「&」で繋ぐ形で作成します。

それを踏まえて、以下の様な形で処理を組みました。

import urllib.parse
import tkinter, tkinter.filedialog, tkinter.messagebox
from selenium import webdriver


# 認可コードの取得先URL
GET_AUTH_URL = "https://api.thebase.in/1/oauth/authorize?response_type=" \
                "code&client_id=%ID%&redirect_uri=%URI%&scope=%SCOPE%&state=hoge"

'''
-----------------------------------------------------------------
 アプリの連携画面を表示し、ユーザーに認証許可を求める
 許可後、自動的にURLより認可コードを取得して返す
-----------------------------------------------------------------
'''
def get_authorize_code():
    # アクセスURLの作成
    auth_url = GET_AUTH_URL.replace("%ID%","アプリのclient_id")
    auth_url = auth_url.replace("%URI%",urllib.parse.quote("アプリで設定したコールバックURL", safe=''))
    auth_url = auth_url.replace("%SCOPE%",urllib.parse.quote("アプリで設定したスコープ"]))

    driver = webdriver.Chrome("./chromedriver.exe")
    driver.get(auth_url)

    root = tkinter.Tk()
    root.withdraw()
    tkinter.messagebox.showinfo(
        "認証", "アプリの認証ページを表示しました。\n" +
        "ログイン情報入力後、\n" +
        "『アプリを認証する』ボタンを押した後のページでOKを押して下さい。")

    # リダイレクト画面の検出
    while ("アプリで設定したコールバックURL" in driver.current_url) == False:
        if tkinter.messagebox.askyesno(
                "BASE API操作ツール",
                "認証後の画面を確認できません。\n"
                "処理を中断しますか?") == True:
            return

    # URLから認可コードの抽出
    tmp = driver.current_url.split("=")[1]
    code = tmp.split("&")[0]
    driver.quit()

    return code

Pythonの環境構築については省きますので、そちらは事前に用意しておいて下さい。

後、ここでは「selenium」を使っているのでpipからインストールしておいて下さい。次の処理では「requests」も使用するので、あわせてインストールしておくと良いです。

では簡単に解説。

冒頭の処理でパラメータの置き換えを行っていますが、コールバックURLの部分とスコープに関しては「URLエンコード」という処理を行っています。これは一部の文字列をURLとして使用できる形に変換する必要があるためです。

(サンプルではredirect_uriが「http%3A%2F%2F」となっていますが、これは「http://」という文字列をエンコードした状態です。)

ここで置換していない「response_type」と「state」の項目については、固定値で問題無いので最初から定数の中に記述しています。

次にwebdriverを使用してブラウザを立ち上げています。

冒頭で作成したURLにアクセスすると、以下の様な画面が表示されます。

ここでログインを行ってアプリの認証を行う事で、認可コードが発行される仕組みとなっています。

上のPythonコードでは形式上、メッセージボックスを表示して処理を停止させ、ユーザーが手動でログインを行うという方法を取っていますが、ここはログイン処理も自動化させてしまって構いません。(seleniumを入れたのはその為です)

アプリの認証を行った後は自動的にコールバックURLに設定したページに移動しますので、移動した事を検知できたらURLから認可コードを抽出します。

コードの抽出は以下の2行で行っています。

tmp = driver.current_url.split("=")[1]
code = tmp.split("&")[0]

最終的にreturnで認可コードを返す事で、自動的に認可コードを取得する関数の出来上がりです。

スポンサーリンク

認可コードからアクセストークンを取得する

続いて、先ほど取得した認可コードを用いてアクセストークンの発行要求を行います。

アクセストークンの取得方法についてはこちら↓を参照。

POST /1/oauth/token

そしてこちらがコードになります。

import requests
import json
import tkinter, tkinter.filedialog, tkinter.messagebox


POST_TOKEN_URL = "https://api.thebase.in/1/oauth/token"
GRANT_TYPE_AUTHCODE = 'authorization_code'


'''
-----------------------------------------------------------------
 認可コードを使用してリフレッシュトークンを取得する
-----------------------------------------------------------------
'''
def get_refresh_token():

    # ブラウザを自動操作して認可コードの取得を行うため、
    # 事前に確認メッセージを表示する
    if tkinter.messagebox.askyesno(
            "BASE API操作ツール",
            "BASEアプリにアクセスし、認可コードを再取得する必要があります。\n" +
            "ブラウザを起動し、アプリページにアクセスしても宜しいですか?") == False:
        return

    # 認可コードの取得
    auth_code = get_authorize_code()
    if auth_code == "":
        return

    param = {
        'grant_type'    : GRANT_TYPE_AUTHCODE,              	# authorization_code
        'client_id'     : 'アプリのclient_id',			# クライアントID
        'client_secret' : 'アプリのclient_secret',        # クライアントシークレット
        'code'          : auth_code,                        	# 認可コード
        'redirect_uri'  : 'アプリで設定したコールバックURL',   	# 登録したコールバックURL
        }

    response = requests.post(POST_TOKEN_URL, params=param)
    token_data = json.loads(response.text)
    
    # リフレッシュトークンは暫く使い回すため、外部ファイルなどに保存しておく
    save_refreshtoken(token_data["refresh_token"])
    return token_data["refresh_token"]

早速前項で作成した「get_authorize_code()」を使用しています。

get_refresh_token()の名の通り、呼び出す事で自動的にリフレッシュトークンを返してくれます。

「認可コードからアクセストークンを取得する」とは書きましたが、今の所リフレッシュトークンさえあれば良いのでここで取得したアクセストークンは無視します。

処理については見たままなので特に解説はありませんが、今後1ヶ月近くはこのリフレッシュトークンを使いまわすつもりなので、一旦外部ファイルに保存しています。

常時動きっぱなしのサーバアプリであれば特に意識して出力する必要は無いので、ずっとメモリ上に保持しておけば問題ありません。ただしリフレッシュトークンを取得した日付もあわせて保持しておきましょう。

長くなったので一旦区切って次へ。

PythonでBASEのAPIを叩いて商品データを取得してみる -その2-

関連記事と広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

コメント

  1. キハラゲンキ より:

    はじめまして、木原と言います。
    この度拝見して、勉強になりました。

    質問なんですが、100個と指定してダウンロードするとどこの保存されますか?
    アップロードのCSVの形式はありますでしょうか?
    すみません。

    • 藤美れいん より:

      本記事には「100」という数値を使用した解説はございませんが、どの内容の事でしょうか。