前提・実現したいこと
https://api.cryptowat.chから価格データを取得したいが、サイトが不安定のためかたまに空をかえすため
KeyErrorを起こしてしまいます。
そのためエラーが起きても再度 r = requests.getに戻り、エラーが起きなくなるまで繰り返したい。
発生している問題・エラーメッセージ
Key Error: '60'
該当のソースコード
from datetime import datetime, timezone, timedelta
import time
import requests
import json
TIME = 0
CLOSE = 4
while True:
r = requests.get('https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc?periods=60') json = r.json()['result']['60'] close = json[-1][CLOSE] print(str(datetime.fromtimestamp(round(time.time()) + 60 * 60 * 9)) + ' CLOSE: ' + str(close)) #直近の終値の表示 time.sleep(5)
試したこと
独学で勉強しはじめたての初心者のため retry というライブラリがあることまでは発見したのですが、使い方がわからない状況です。。
補足情報(FW/ツールのバージョンなど)
python3.6
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
そもそも、攻める方向を間違ってるような気がします。
なんか空を返すからリトライしたい、じゃなく、なぜ空を返すのかの原因を突き止めるのが先じゃないのでしょうか。
それがわからないと、リトライするのが有効なのかそうじゃないのか、リトライするにしてもどういうふうにリトライしなければならないのかもわからないって話で、この質問のスレッド自体、意味がない気がしますが。
投稿2018/03/23 02:55
総合スコア87715
0
ベストアンサー
<< 回答が長くなったので、最新のソースコード以外は削除しました。 >>
Can I set max_retries for requests.request?
上記サイトを参考にRetry処理を実装してみてはー。
公開APIには負荷を掛けないように一度取得したものは、2度取得しないような形にしてくださいな。
例えばファイルに書き出して、読み込む形にするなどの対応をしてくださいな。
そうしないとAPIに負荷がかかりすぎて、APIからのアクセス拒否が行われたりやAPIが閉鎖され2度と使えなくなる事もあります。
■参考情報
python requestsでリトライ処理をする
2018/03/23追記
cryptowatch.jp APIのドキュメントを見ると、レートリミットになるとステータスコード:429を返すみたいですね。
APIから帰ってくるステータスコード判定してませんようね・・多分。。
■参考情報
cryptowat APIの使い方(備忘録)
質問文のコードに合わせる形で修正
Python
1import time 2from datetime import datetime 3import json 4import requests 5from urllib3.util.retry import Retry 6from requests.adapters import HTTPAdapter 7 8 9def get_content(url: str='https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc'): 10 s = requests.Session() 11 retries = Retry(total=5, 12 backoff_factor=0.1, 13 status_forcelist=[500, 502, 503, 504]) 14 s.mount('https://', HTTPAdapter(max_retries=retries)) 15 payload = {'periods': '60'} 16 r = s.get(url, params=payload) 17 # ↓テスト用コード 18 # r.status_code = 429 19 if r.status_code == 429: 20 # APIのドキュメントにはr.json()できるかどうかの保証の記述はなかったので注意です。 21 # r.json()出来ない場合は値:Noneを返してくださいな。 22 return r.json(), r.status_code 23 return r.json(), r.status_code 24 25 26def data_write(obj): 27 file_name = f'{datetime.now().strftime("%Y%m%d_%H%M%S_%f")}.json' 28 #print(f'file write:{file_name}') 29 with open(file_name, 'w', encoding='utf-8-sig') as f: 30 json.dump(obj, f) 31 32 33def main() -> None: 34 CLOSE = 4 35 while True: 36 content, status_code = get_content() 37 # rate_limitなら 38 if status_code == 429: 39 # sleepタイムを55秒に 40 time.sleep(55) 41 continue 42 43 json = content['result']['60'] 44 close = json[-1][CLOSE] 45 print(str(datetime.fromtimestamp(round(time.time()) + 60 * 60 * 9)) + ' CLOSE: ' + str(close)) # 直近の終値の表示 46 # ファイルに保存したい時。 47 #data_write(json) 48 49 time.sleep(5) 50 51 52if __name__ == '__main__': 53 main() 54
投稿2018/03/22 13:42
編集2018/03/23 06:21総合スコア5846
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/23 02:55
退会済みユーザー
2018/03/23 05:01
2018/03/23 05:09
退会済みユーザー
2018/03/23 05:41
退会済みユーザー
2018/03/24 03:03
0
投稿2018/03/22 11:28
総合スコア1167
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/03/22 11:36
2018/03/22 11:55
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/23 02:56 編集