You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.6下Requests/urllib无法通过代理使用HTTPS的问题求助

Fixing HTTPS Proxy Stalls in Python 3.6 (Requests & urllib)

我之前维护老项目用Python 3.6的时候也踩过一模一样的坑!问题根源很明确:Python 3.6里的urllib(包括依赖它的Requests)默认会用HTTP/1.0发送CONNECT请求,而很多现代代理已经不再兼容这个老旧的协议版本了——这就是为什么你的进程会永久卡住,代理压根就不响应这个旧格式的请求。而curl默认用的是HTTP/1.1,所以能正常建立连接。

下面是针对两个库的具体解决方案:

解决urllib的代理问题

我们可以自定义一个代理处理器,强制让CONNECT请求使用HTTP/1.1:

import urllib.request
import http.client

# 自定义代理处理器,强制使用HTTP/1.1发送CONNECT
class HTTP11ProxyHandler(urllib.request.HTTPProxyHandler):
    def connect(self, req):
        # 建立到代理的HTTP连接
        conn = http.client.HTTPConnection(self.proxy_host, self.proxy_port)
        # 设置隧道目标,带上请求头
        conn.set_tunnel(req.host, req.port, headers=req.headers)
        # 用HTTP/1.1发送CONNECT请求
        conn.request("CONNECT", "/", "", req.headers)
        response = conn.getresponse()
        # 检查代理是否返回连接成功
        if response.status != 200:
            raise urllib.error.URLError(f"Proxy connection failed: {response.status} {response.reason}")
        # 返回建立好的socket
        return conn.sock

# 配置代理并构建opener
proxy_settings = {"https": "http://127.0.0.1:8899"}
proxy_handler = HTTP11ProxyHandler(proxy_settings)
opener = urllib.request.build_opener(proxy_handler)
urllib.request.install_opener(opener)

# 测试请求
try:
    response = urllib.request.urlopen("https://example.com")
    print(response.read().decode("utf-8"))
except Exception as e:
    print(f"Error: {e}")

解决Requests的代理问题

Requests底层依赖urllib3,所以我们可以通过修改urllib3的协议版本来解决,有两种方式:

方式一:全局修改urllib3配置(简单直接)

import requests
from urllib3.connection import HTTPConnection

# 强制urllib3使用HTTP/1.1
HTTPConnection._http_vsn = 11
HTTPConnection._http_vsn_str = 'HTTP/1.1'

# 配置代理并发送请求
proxies = {
    "https": "http://127.0.0.1:8899"
}

try:
    response = requests.get("https://example.com", proxies=proxies)
    print(response.text)
except Exception as e:
    print(f"Error: {e}")

方式二:自定义适配器(更优雅,不影响全局)

如果不想修改全局设置,可以给Requests会话挂载一个自定义适配器,只针对特定请求生效:

import requests
from urllib3.poolmanager import PoolManager
from urllib3.connection import HTTPConnection

class HTTP11Adapter(requests.adapters.HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        # 创建使用HTTP/1.1的连接池管理器
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            connection_class=lambda *args, **kwargs: HTTPConnection(
                *args,
                _http_vsn=11,
                _http_vsn_str='HTTP/1.1',
                **kwargs
            )
        )

# 创建会话并挂载适配器
session = requests.Session()
session.mount("https://", HTTP11Adapter())

# 配置代理并发送请求
proxies = {
    "https": "http://127.0.0.1:8899"
}

try:
    response = session.get("https://example.com", proxies=proxies)
    print(response.text)
except Exception as e:
    print(f"Error: {e}")

额外注意事项

  • 如果代理需要认证,直接在代理URL里加上用户名和密码即可,比如:"https": "http://username:password@127.0.0.1:8899"
  • Python 3.6已经停止维护了,如果条件允许,尽量升级到更高版本(比如3.8+),新版本的urllib/Requests默认已经使用HTTP/1.1发送CONNECT请求,不会有这个问题。

内容的提问来源于stack exchange,提问作者Jorjon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:35:15