ドバイのコワーキングスペースで書いています。
新しいプロジェクトの予備的な分析のためにスクレイピングでデータを集めようと2年前に書いたコードを走らせたら動かなくなっていた。[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]とのことで、SSL通信周りのエラーっぽい。requestsでURL指定してgetしただけなんだけど、おおよそのエラー内容を貼っておく。
SSLError: [SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1007) During handling of the above exception, another exception occurred: SSLError Traceback (most recent call last) SSLError: [SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1007) The above exception was the direct cause of the following exception: MaxRetryError Traceback (most recent call last) MaxRetryError: HTTPSConnectionPool(host='www.cosme.net', port=443): Max retries exceeded with url: /product/product_id/10010221/top (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1007)'))) During handling of the above exception, another exception occurred: SSLError Traceback (most recent call last) /usr/local/lib/python3.10/dist-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies) 515 if isinstance(e.reason, _SSLError): 516 # This branch is for urllib3 v1.22 and later. --> 517 raise SSLError(e, request=request) 518 519 raise ConnectionError(e, request=request) SSLError: HTTPSConnectionPool(host='www.cosme.net', port=443): Max retries exceeded with url: /product/product_id/10010221/top (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1007)')))
要はSSLで通信するのに古臭い方法でアタックかけてるのが悪いわけですね。ということでサクッと直す。
たとえば、Googleのトップページ(https://google.co.jp)を取ってきたければこんな感じになる。
import requests, ssl, urllib3
url = 'https://www.google.co.jp/'
class CustomHttpAdapter (requests.adapters.HTTPAdapter):
def __init__(self, ssl_context=None, **kwargs):
self.ssl_context = ssl_context
super().__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = urllib3.poolmanager.PoolManager(
num_pools=connections, maxsize=maxsize,
block=block, ssl_context=self.ssl_context)
session = requests.session()
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4
session.mount('https://', CustomHttpAdapter(ctx))
res = session.get(url)
print(res.content)

これは2行目のurlの変数の値を変えるだけで動くようになったので、ついでに関数化しておく。
import requests, ssl, urllib3
class CustomHttpAdapter (requests.adapters.HTTPAdapter):
def __init__(self, ssl_context=None, **kwargs):
self.ssl_context = ssl_context
super().__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = urllib3.poolmanager.PoolManager(
num_pools=connections, maxsize=maxsize,
block=block, ssl_context=self.ssl_context)
def get_url(url='https://www.google.co.jp/'):
session = requests.session()
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4
session.mount('https://', CustomHttpAdapter(ctx))
res = session.get(url)
return res.content
get_url('https://stackoverflow.com/questions/71603314/ssl-error-unsafe-legacy-renegotiation-disabled')

これでget_url()に欲しいURL指定するだけで指定URLの中身を取ってくるようになる。
やっぱ昔書いたコードの保守ってめんどくさいなあ。まあこれはこの先も使うだろうから仕方ないけどね。
今回のエラー対応は以下の内容を参考にしました。
SSL error unsafe legacy renegotiation disabled – StackOverflow (https://stackoverflow.com/questions/71603314/ssl-error-unsafe-legacy-renegotiation-disabled)