HTTP プロキシ事業者が提供する IPv4 形式 ip:port:user:password では、値を Requests に渡す前に各フィールドを変換します。

from ipaddress import IPv4Address
from urllib.parse import quote

def proxy_map(line):
    host, port, user, password = line.rstrip('\r\n').split(':', 3)
    host = str(IPv4Address(host))
    port = int(port)
    if not 1 <= port <= 65535:
        raise ValueError('Proxy port is out of range')
    credentials = quote(user, safe='') + ':' + quote(password, safe='')
    url = f'http://{credentials}@{host}:{port}'
    return {'http': url, 'https': url}

範囲限定の分割により、パスワード内に含まれる追加のコロンがそのまま保持されます。改行だけを除去すれば、認証情報の一部である可能性のある空白を黙って削り取ることもありません。

ユーザー名とパスワードを個別の URL コンポーネントとしてエンコードします。生のパスワード内の @ を、プロキシホスト前の区切り文字と取り違えてはいけません。この関数は生の認証情報を想定しています。すでにエンコード済みの文字列を渡すと、パーセント記号が二重にエンコードされる可能性があります。

返されるマップは、HTTP と HTTPS の宛先に対してこのプロキシを選択します。http://192.0.2.10 のようなキーは Requests では別の意味を持ち、その宛先ホスト向けの経路を選びます。プロキシサーバーのプールの添字ではありません。

パーサーは記載された IPv4 形式だけを意図的に受け付けます。コロンを含むユーザー名や、角括弧のない IPv6 アドレスは対象外です。これらには曖昧さのない入力形式が必要です。生成した認証情報付き URL は通常のログに残さないでください。

関連記事