Python Requests代理密码含#致URL解析失败,求解决方案
问题场景
代理地址为:http://abc:zyx#123$@http://proxy.mycompany.com:8800/,执行以下代码时:
response = requests.get( url, stream=True, headers=headers, proxies=my_proxies)
出现解析错误:
requests.exceptions.InvalidURL: Failed to parse: http://abc:zyx#123$@http://proxy.mycompany.com:8800/
移除密码中的#后,又出现代理连接错误:
requests.exceptions.ProxyError: HTTPSConnectionPool(host='api.precisely.com', port=443): Max retries exceeded with url: /oauth/token (Caused by ProxyError('Unable to connect to proxy', NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x00000202D2877190>: Failed to resolve 'http' ([Errno 11001] getaddrinfo failed)")))
问题根源
- 密码中的
#是URL保留字符,直接写入会被解析为锚点分隔符,导致代理地址结构错乱,触发InvalidURL错误。 - 代理地址格式错误:
@后多了http://,导致解析时把http当成代理主机名,触发域名解析失败的ProxyError。
解决步骤
1. 对密码中的特殊字符进行URL编码
使用Python内置的urllib.parse.quote方法,对包含特殊字符的密码进行编码,转义URL保留字符(比如#、$)。
2. 修正代理地址格式
去掉@后的多余http://,正确的代理地址格式应为:协议://用户名:编码后的密码@代理主机:端口
完整代码示例
import requests from urllib.parse import quote # 原始用户名和密码 username = "abc" password = "zyx#123$" # 对密码进行URL编码 encoded_password = quote(password) # 构造正确的代理地址 proxy_host = "proxy.mycompany.com" proxy_port = 8800 proxy_url = f"http://{username}:{encoded_password}@{proxy_host}:{proxy_port}" # 代理字典配置 my_proxies = { "http": proxy_url, "https": proxy_url } # 发起请求 response = requests.get(url, stream=True, headers=headers, proxies=my_proxies)
验证说明
编码后的密码会把#转为%23、$转为%24,最终代理地址变为http://abc:zyx%23123%24@proxy.mycompany.com:8800/,requests可以正确解析该地址,同时避免域名解析错误。
内容的提问来源于stack exchange,提问作者J Z

