API使ってデータ取得しようとした際にハマったのでメモ。
環境はpython3.6.4。
以下ハマったスクリプト。
import json
import urllib.request, urllib.error
#リクエストするアドレス
request_url="***********************"
#検索開始日付
PARAM_START_DATE="2018-09-01"
#検索終了日付
PARAM_END_DATE="2018-09-30"
#API-KEYのセット
API_KEY="***********************"
headers = {'x-api-key': API_KEY, "Content-Type":"application/json"}
request_json={
"start_date":PARAM_START_DATE,
"end_date":PARAM_END_DATE
}
req = urllib.request.Request(url=request_url, headers=headers, data=json.dumps(request_json).encode())
f = urllib.request.urlopen(req)
response = f.read()
f.close()
上記スクリプトを流したところSSL認証エラー。
urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
verify = Falseを設定すれば解決できるようだが、最終的にはお仕事で使う必要があり、あまりやりたくなかったので別の解決策を模索。
参考 → Python requests で SSLError が起きて毎回ググってるのでまとめた
諸々調べた所、上記のエラーはpython2.7.9以降で出現するという記事を見たので、試しにpython2.7.8にバージョンを落として実行してみたところ、今度は以下のエラー。
SSL証明書が正しくないサイトに対してPythonでアクセスする
urlopen error [Errno 1] _ssl.c:510: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
バージョン下げればいいとかそういう問題ではない模様。
handshakeについて → SSL/TLS(SSL3.0~TLS1.2)のハンドシェイクを復習する
#####解決策
SSLContextを使えば認証方法を設定する事が可能とのことなので試してみる。
公式リファレンス → https://docs.python.jp/3/library/ssl.html#ssl.SSLContext
import json
import urllib.request, urllib.error
#認証方法をTLSv1に指定
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
#リクエストするアドレス
request_url="***********************"
#検索開始日付
PARAM_START_DATE="2018-09-01"
#検索終了日付
PARAM_END_DATE="2018-09-30"
#API-KEYのセット
API_KEY="***********************"
headers = {'x-api-key': API_KEY, "Content-Type":"application/json"}
request_json={
"start_date":PARAM_START_DATE,
"end_date":PARAM_END_DATE
}
req = urllib.request.Request(url=request_url, headers=headers, data=json.dumps(request_json).encode())
#context=TLSv1に指定
f = urllib.request.urlopen(req,context=context)
response = f.read()
f.close()
これで動きました。