【手順を丁寧に解説】Pythonのrequest.getでSSLのエラーが出たときの解決方法

Featured image of the post

はじめに

Pythonでrequests.get("https://xxxx.com")を実行したら以下のエラーが発生した😰

そのときの解決方法と解決までの流れをまとめる💡

(Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))

⚠️
エラー解決したときの備忘録としてご参考程度にお読みください。
PythonやSSL証明書に関しては詳しくないため情報が正確でない場合があります。

結論

✅コードの修正は不要。

✅certifiにSSL証明書の情報を書き加えたら解決する。

現象が出るコード

以下のシンプルなコードでエラーが出た😅

import requests

# ここでエラー(xxxx.comは仮)
html = requests.get("https://xxxx.com")

print(html)

原因

✅ライブラリ「certifi」が持つルート証明書のリストに、"https://xxxx.com"のSSL証明書の情報が不足していることが原因。

【補足】ライブラリ「certifi」って何?requestsとどう関係あるの?

解決方法

調査したこと
SSL証明書のルート証明書ってそもそもなんだっけ?

まずSSL証明書を理解していないと調査できないので簡単におさらいしておいた😊

[SSL: CERTIFICATE_VERIFY_FAILED]のエラーについて調べる

とりあえず参考になりそうなサイトを読んだ😊

その結果……

💡
「cacert.pem」というファイルにhttps://xxxx.comのSSL証明書の情報が欠落しているのかな?💭という仮説が立った。

【補足】cacert.pemについて

✅cacert.pemは、ライブラリ「certifi」で使われているファイル。ルート証明書の情報が書かれている。

解決方法

✅cacert.pemにhttps://xxxx.comのSSL証明書の情報を追記すれば解決する!

cacert.pemに追記するSSL証明書の情報を調べる

以下のサイトで調べたいホスト名「xxxx.com」を入力すると、SSL証明書の情報を調べられる。

※実行に数分かかる。

具体的には以下の手順。

Image in a image block

Image in a image block

Image in a image block

ここに出てくる「----BEGIN CERTIFICATE-----」のような文字列が必要なSSLの情報。

Image in a image block

cacert.pemにSSL証明書の情報を追記する

以下のコマンドで既存のcacert.pemを探す。

pip show certifi

すると結果に以下のようにパスが出てくる。このフォルダにcacert.pemがある。

Location: c:\python310\lib\site-packages

cacert.pemをテキストエディタで開き、末尾にさっきコピーしたSSL証明書の情報を貼り付ける。

Image in a image block

再度プログラムを実行してみる

コードの修正は一切不要。これで無事に動作した。

import requests

# エラーが出なくなっている!
html = requests.get("https://xxxx.com")

print(html)

【補足】既存のcacert.pemを触らずに解決する方法

先ほどの方法では「c:\python310\lib\site-packages」にあるcacert.pemを修正したが、これだと他のプログラムにも影響する。

このファイルを直接触らない方法も解説する。

以下の3ステップでOK。

  • cacert.pemをプロジェクトフォルダ直下にコピーする。
  • コピーしたcacert.pemの末尾にさっきコピーしたSSL証明書の情報(「----BEGIN CERTIFICATE-----」のような文字列)を貼り付ける。
  • コードを修正する。
    import requests
    
    # プロジェクトフォルダ内にあるcacert.pemを使うように設定
    html = requests.get("https://xxxx.com", verify='cacert.pem')
    
    print(html)

参考サイト