結論
- ブラウザ自動化ツール (Selenium等) を使う
- ブロックを回避できるcliのツールを使う
問題
- いつものようにPythonのrequestsでアクセスしようとすると
SSLError
が発生requests.exceptions.SSLError: HTTPSConnectionPool(host='ss148.litvp.com', port=443): Max retries exceeded with url:
- ブラウザからはアクセスできる
- cloudflareのサイトが多い
なぜアクセスできないのか
- ボット対策
- TLSフィンガープリントなどを使ってクライアントを見分けている
- 詳細は以下の記事が参考になる
1. ブラウザ自動化ツールを使う
- メリット
- 実際のブラウザを動かすため、実環境と同様にアクセスできる
- デメリット
- その分、動作速度が遅いことやメモリ使用量が多いことなどのデメリットがある
2. ブロックを回避できるcliのツールを使う
- メリット
- 必要なアクセスのみを行うため、ブラウザ自動化ツールとくらべて軽量
- デメリット
- cliのツールなのでPythonなどで使うときには、subprocessなどでコマンドを実行する必要がある
- 例
- Windows:
Invoke-WebRequest
, wslでcurl-impersonate
- Mac, Linux:
curl-impersonate
- Windows:
curl-impersonateのラッパー
エスケープがあたりが怪しい。あくまで参考に
import os
import subprocess
def get_from_curl_impersonate(url, headers=None):
# -s 途中経過の非表示
# -L リダイレクトを追跡する (Locationヘッダ)
if os.name == 'nt':
dirpath = '~/scripts/others/curl-impersonate/'
replaced_url = url.replace('"', '""')
command = f"wsl {dirpath}curl_chrome104 -s -L \"{replaced_url}\""
elif os.name == 'posix':
replaced_url = url.replace('"', '\\"')
command = f'curl_chrome104 -s -L "{replaced_url}"'
else:
raise OSError('このOSにはまだ対応していません')
if headers is not None:
headers_str = ''
for key, value in headers.items():
if os.name == 'nt':
formatted_key = key.replace('"', '""')
formatted_value = value.replace('"', '""')
headers_str += f"-H \"{formatted_key}: {formatted_value}\" "
else:
formatted_key = key.replace('"', '\\"')
formatted_value = value.replace('"', '\\"')
headers_str += f'-H "{formatted_key}: {formatted_value}" '
command += f" {headers_str}"
result = subprocess.run(command, shell=True, capture_output=True)
html_str = result.stdout.decode()
if result.stderr is not None and result.stderr != b'':
print(result.stderr.decode(), file=sys.stderr)
return html_str