見出し画像

J-Quants APIトークン取得を書き直し

ご注意:2023/04/03 より正式に運用が開始されました。正式版の接続URLは、β版と異るので読み替えて下さい。また、仕様もいろいろアップデートされている様です。
なお β版の運用は、2023/04/10で終了とのことです。

トークン取得部分を修正

「J-Quants API への接続」で書いたコードは余りにも使い勝手を無視したものでした。ほぼサンプルコードの繋ぎ合せです。
反省して少し作り直してみました。

プログラムは、リフレッシュトークン取得と、IDトークン取得に分けました。

Githubにアップしました。
J-Quants API リフレッシュトークンの取得 こちら
J-Quants API IDトークンの取得 こちら


リフレッシュトークン取得

入力は、コマンドラインの引数で、[YOUR_MAIL_ADDRESS] [YOUR_PASSWORD] を渡します。
簡単な --help も用意しました。

取得したリフレッシュトークンは、ファイルに保存します。
デフォルトのファイル名: jq_rftoken.json
データ形式:
{"time_rftoken":"YYYY-mm-dd HH:MM:SS.ffffff","refreshToken":"value"}
です。


# -*- coding: utf-8 -*-
# 2022.10.04 coded by yo.
# MIT License
# Python 3.6.8 / centos7.4

import urllib3
import requests
import datetime
import json
import sys
from datetime import datetime as dt


# ---------------------------------------------
# 機能: コマンドライン入力のパラメーターをチェックする。
# 引数1: コマンドライン入力のパラメーター(list型)
# 引数2: 出力ファイル名(string型)
# 返値: なし
# ---------------------------------------------
def func_parse_parameter(list_argv, str_fname_output):
    if len(list_argv) == 3 :
        pass
    elif len(list_argv) == 2 :
        if list_argv[1] == '-h' \
            or list_argv[1] == '--help':
            print(list_argv[0], ' [YOUR_MAIL_ADDRESS] [YOUR_PASSWORD]')
            print('filename_output :', './' + str_fname_output)
            exit()
        else :
            print(list_argv[0], ' [YOUR_MAIL_ADDRESS] [YOUR_PASSWORD]')
            exit()
            
    elif len(list_argv) == 1 or len(list_argv) > 3 :
        print(list_argv[0], ' [YOUR_MAIL_ADDRESS] [YOUR_PASSWORD]')
        exit()

        

# ---------------------------------------------
# 機能 : J-QuantsAPIからリフレッシュトークンを取得する。
# 引数1: J-Quants API接続先URL(string型)
# 引数2: J-Quants登録メールアドレス(string型)
# 引数3: J-Quants登録パスワード(string型)
# 返値 : リフレッシュトークン
# ---------------------------------------------
def func_get_rftoken(api_url, str_mail_address, str_password):
    
    # リフレッシュトークン取得
    data={}
    data["mailaddress"] = str_mail_address
    data["password"] = str_password
    r_post_rftoken = requests.post(api_url, data=json.dumps(data))
    dic_rftoken = json.loads(r_post_rftoken.text)  # 辞書型に変換
    return dic_rftoken



# ---------------------------------------------
# 機能 : 起動したディレクトリでファイルに書き込む。
# 引数1: 出力ファイル名(string型)
# 引数2: 出力文字列(string型)
# 返値 : 無し
# ---------------------------------------------
def func_write_to_file(str_fname_output, str_text):
    try:
        with open(str_fname_output, 'w', encoding = 'utf_8') as fout:
            fout.write(str_text)     

    except IOError as e:
        print('Can not Write!!!')
        print(type(e))



# =============================================

# J-Quants API接続先URL
api_url = "https://api.jpx-jquants.com/v1/token/auth_user"

# 出力ファイル名
str_fname_output = 'jq_rftoken.json'


# コマンドライン引数のチェック
func_parse_parameter(sys.argv, str_fname_output)

# リフレッシュトークンを取得した時刻を取得
time_rftoken = datetime.datetime.now()

# リフレッシュトークンを取得 (有効期限は1週間)
dic_rftoken = func_get_rftoken(api_url, sys.argv[1], sys.argv[2])
str_rftoken = dic_rftoken.get('refreshToken')    # IDトークンのvalueを取得
# リフレッシュトークンを取得できなかった場合
if str_rftoken is None :
    print('message :', dic_rftoken.get('message'))
    quit()  # 終了


# 取得時刻とリフレッシュトークンを保存
# データ形式は、{"time_rftoken":"value","refreshToken":"value"}
dic_json = {}
dic_json['time_rftoken'] = str(time_rftoken)
dic_json['refreshToken'] = str_rftoken
str_json=json.dumps(dic_json)
func_write_to_file(str_fname_output, str_json)

print('refresh token saved :', str_fname_output )
print('format =','{"time_rftoken":"YYYY-mm-dd HH:MM:SS.ffffff","refreshToken":"value"}')
print()

# リフレッシュトークンの取得時間を表示
print('time stamp :', time_rftoken)

# リフレッシュトークンの有効期限を表示
expire_span = datetime.timedelta(days=7)
expire_time = time_rftoken + expire_span
print('expiry date:', expire_time)
print('リフレッシュトークンの有効期間は1週間です。')

こっそり翌日にイッパイ直してしまいました(笑


IDトークンの取得

ファイルに保存されたリフレッシュトークンを読み出し、J-Quants APIに接続しIDトークンを取得します。

デフォルト設定は
入力ファイル名: jq_rftoken.json
データ形式: json
{"time_rftoken":"YYYY-mm-dd HH:MM:SS.ffffff","refreshToken":"value"}

出力ファイル名: jq_idtoken.json
データ形式: json
{"time_idToken":"YYYY-mm-dd HH:MM:SS.ffffff","idToken":"value"}
です。

# -*- coding: utf-8 -*-
# 2022.10.03 coded by yo.
# MIT License
# Python 3.6.8 / centos7.4

import urllib3
import requests
import datetime
import json
## import time
import sys
from datetime import datetime as dt



# ---------------------------------------------
# 機能 : 起動したディレクトリでファイルに書き込む。
# 引数1: 出力ファイル名(string型)
# 引数2: 出力文字列(string型)
# 返値 : 無し
# ---------------------------------------------
def func_write_to_file(str_fname_output, str_text):
    try:
        with open(str_fname_output, 'w', encoding = 'utf_8') as fout:
            fout.write(str_text)     

    except IOError as e:
        print('Can not Write!!!')
        print(type(e))



# ---------------------------------------------
# 機能 : 起動したディレクトリでファイルに書き込む。
# 引数1: 出力ファイル名(string型)
# 引数2: 出力文字列(string型)
# 返値 : 無し
# ---------------------------------------------
def func_read_from_file(str_fname):
    str_read = ''
    try:
        with open(str_fname, 'r', encoding = 'utf_8') as fin:
            while True:
                line = fin.readline()
                if not len(line):
                    break
                str_read = str_read + line
        return str_read

    except IOError as e:
        print('Can not Write!!!')
        print(type(e))



# =============================================

# IDトークン保存ファイル名
str_fname_output = 'jq_idtoken.json'

# リフレッシュトークンファイル名
str_fname_rftoken = 'jq_rftoken.json'



# リフレッシュトークンの読み出し
str_rf_json = func_read_from_file(str_fname_rftoken)
dic_rf_json = json.loads(str_rf_json)
str_rftoken = dic_rf_json.get('refreshToken')

# IDトークン取得用urlの作成
str_url_auth_refresh = 'https://api.jpx-jquants.com/v1/token/auth_refresh'
str_url_idtoken = str_url_auth_refresh + '?' + 'refreshtoken=' + str_rftoken


# リフレッシュトークンのタイムスタンプを取得し時間型に変換
str_time_rftoken = dic_rf_json.get('time_rftoken')
time_rftoken = dt.strptime(str_time_rftoken, '%Y-%m-%d %H:%M:%S.%f')

# リフレッシュトークンの有効期限
expire_span = datetime.timedelta(days=7)
time_expire = time_rftoken + expire_span
print('リフレッシュトークンの有効期限')
print('rftoken saved :', time_rftoken)
print('effective date:', time_expire)

time_remain = time_expire - datetime.datetime.now()
print('remaining time:', time_remain)
print('----------------------------------')
print()


# IDトークンを取得した時刻を取得
time_idtoken = datetime.datetime.now()

# IDトークン取得
r_post_idtoken = requests.post(str_url_idtoken)
dic_idtoken = json.loads(r_post_idtoken.text)  # 辞書型に変換
str_idtoken = dic_idtoken.get('idToken')    # IDトークンのvalueを取得

# -- こっそり翌日に直しました(笑 --
# リフレッシュトークンが正しくない場合、有効期限切れの場合
if str_idtoken is None :
    print(dic_idtoken.get('message'))
    quit()
# -- 以上こっそり直した部分 --

# 取得時刻とIDトークンを保存
# データ形式は、{"time_idtoken":"value","idToken":"value"}
dic_json = {}
dic_json['time_idToken'] = str(time_idtoken)
dic_json['idToken'] = str_idtoken
str_json=json.dumps(dic_json)
func_write_to_file(str_fname_output, str_json)
print('ID token saved :', str_fname_output )
print('format =','{"time_idToken":"YYYY-mm-dd HH:MM:SS.ffffff","idToken":"value"}')
print()
# IDトークンの取得時間を表示
print('time stamp :', time_idtoken)

# IDトークンの有効期限を表示(有効期限24時間)
expire_span = datetime.timedelta(days=1)
expire_time = time_idtoken + expire_span
print('expiry date:', expire_time)
print('IDトークンの有効期間は24時間です。')

この2つを使えば、API利用で毎回トークンを取得する必要がなくなりました。

IDトークンの読み出し

IDトークンの読み出しは、以下のコードです。
リフレッシュトークンの読み出しの使い回しです(笑

# ---------------------------------------------
# 機能 : 起動したディレクトリでファイルに書き込む。
# 引数1: 出力ファイル名(string型)
# 引数2: 出力文字列(string型)
# 返値 : 無し
# ---------------------------------------------
def func_read_from_file(str_fname):
    str_read = ''
    try:
        with open(str_fname, 'r', encoding = 'utf_8') as fin:
            while True:
                line = fin.readline()
                if not len(line):
                    break
                str_read = str_read + line
        return str_read

    except IOError as e:
        print('Can not Write!!!')
        print(type(e))



# IDトークン保存ファイル名
str_fname_idtoken = 'jq_idtoken.json'


# リフレッシュトークンの読み出し
str_id_json = func_read_from_file(str_fname_idtoken)
dic_id_json = json.loads(str_id_json)
str_idtoken = dic_id_json.get('idToken')

コードが、少し長くなってしまいました。Githubに上げた方が良いのでしょうかね。

今気付いたのですが、リフレッシュトークンが有効期限切れの場合のエラー処理を書いていないです。これはまずいです。
また明日こっそり記事を訂正します(笑


本記事上の私が作成したプログラムは自由にご使用ください。但し、この記事のソフトウェアを使用したことによって生じたすべての障害・損害・不具合等に関して、私と私の関係者および私の所属するいかなる団体・組織とも、一切の責任を負いません。各自の責任においてご使用ください。

この記事が気に入ったらサポートをしてみませんか?