对于 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 远离日常日志。

相关文章