症状
- urllib.request.urlopen などの httpsアクセス結果が以下になってしまう
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1076)
- feedparser.parse の返り値を出力すると以下になってしまう
{'bozo': True, 'entries': [], 'feed': {}, 'headers': {}, 'bozo_exception': URLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1076)'))}
原因
- OpenSSL使用時(httpsアクセス時)の証明書パスがおかしい
確認方法は以下。
python -c "import ssl;print(ssl.get_default_verify_paths())"
上記コマンドの結果が以下。
DefaultVerifyPaths( cafile='C:\\Users\\(ユーザー名)\\anaconda3\\lib\\site-packages\\certifi\\cacert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='C:\\Program Files\\Common Files\\SSL/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='C:\\Program Files\\Common Files\\SSL/certs' )
openssl_cafile が C:\\Program Files\\Common Files\\SSL/cert.pem になっているが、そのパスには cert.pem が存在していなかった。
そして、openssl_cafile, openssl_capath は OpenSSL にハードコードされているらしく、それらを変更する方法を見つけることができなかった。
つまり、OpenSSL使用時に存在しない pem を使用しようとしていることが原因。
対処法
備考
- REQUESTS_CA_BUNDLE を設定してもダメだった
- デフォルト挙動の openssl_cafile がそもそも機能していないので、これを何とかする方法はないのか?
- OpenSSL を openssl_cafile のパス指定でインストールし直すとか
- 環境変数で openssl_cafile を設定するとか(Windows の環境変数 OPENSSL_CAFILE を設定してもダメだった)