代理密码中的特殊字符
分别编码代理用户名与密码,避免 @、冒号、斜杠和 # 破坏 URL。
即使凭据正确,含有 @ 或 # 的密码也可能让手工拼接的代理 URL 出错。这些字符在 URL 中已有特定含义,客户端可能因此将部分密码解析成主机名或片段。
分别编码两个凭据字段
此示例保留 URL 的结构分隔符,只编码用户名和密码:
from urllib.parse import quote
username = "user@team"
password = "p:a/ss#?"
proxy_url = (
"http://"
+ quote(username, safe="")
+ ":"
+ quote(password, safe="")
+ "@203.0.113.10:8080"
)
使用实际的端点与凭据。这里的地址是文档示例。safe 参数为空很重要:quote 通常不转义斜杠,但凭据字段中的斜杠需要编码。
不要编码整个代理 URL。若编码协议方案的分隔符及凭据与主机之间的 @,就会破坏原本想保留的结构。也不要对已编码的密码再次编码。
在 Requests 中使用结果
import requests
response = requests.get(
"https://example.com/",
proxies={"http": proxy_url, "https": proxy_url},
timeout=(5, 15),
)
response.raise_for_status()
若请求仍失败,检查是代理拒绝了登录,还是客户端更早在解析或连接阶段失败。407 认证质询与无效 URL 是不同的故障。
HTTPX 可以将认证信息分开处理
HTTPX Proxy 对象可以分别接收端点与凭据参数:
import httpx
proxy = httpx.Proxy(
"http://203.0.113.10:8080",
auth=("user@team", "p:a/ss#?"),
)
with httpx.Client(proxy=proxy, trust_env=False, timeout=15) as client:
response = client.get("https://example.com/")
response.raise_for_status()
这避免了自行构造 userinfo 部分。它既不会独立于代理连接另行加密凭据,也不会为你选择一种所有服务都支持的认证方式。
如果免费列表只提供 IP 和端口,本示例并不提供默认凭据。只有运营方确实提供账户时才使用认证。不要将含凭据的 URL 写入共享日志和源文件。