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

为何http.client请求正常,requests却出现读取超时或403错误?

问题分析:requests请求超时/403,http.client可正常访问

问题现象

请求https://img.uefa.com/imgml/uefacom/uel/social/og-default.jpg时:

  • 用requests.get()无请求头返回403,添加请求头则触发读取超时
  • 用http.client、curl命令、浏览器均可正常获取200状态码响应

核心差异:requests与http.client的默认行为区别

requests基于urllib3封装,默认会做一些额外处理,和http.client的原生请求逻辑存在差异,这是问题的根源:

  1. 请求头默认配置不同
    requests默认会添加Accept-Encoding: gzip, deflate, br(启用压缩),同时默认User-Agent为python-requests/x.x.x,这类标识容易被反爬规则识别返回403;而http.client默认不带这两个请求头,curl和浏览器则使用合法的客户端标识。部分服务器对压缩编码的处理存在兼容性问题,会导致请求卡住超时。
  2. 连接与重试机制差异
    requests默认开启连接池和重试策略,而http.client是单次连接模式。如果服务器对重复连接有拦截,或者重试触发了反爬限制,就会出现超时或403。
  3. SSL/TLS上下文细节差异
    requests的默认SSL上下文和http.client手动创建的ssl._create_unverified_context()在TLS版本协商、加密套件选择上可能存在区别,部分服务器会因这些细节拒绝连接。

针对性解决办法

方案1:模拟http.client的请求头配置

禁用压缩编码,设置合法的客户端标识:

import requests

url = 'https://img.uefa.com/imgml/uefacom/uel/social/og-default.jpg'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
    'Accept-Encoding': None  # 禁用压缩,和http.client保持一致
}

try:
    response = requests.get(url, headers=headers, verify=False, timeout=10)
    response.raise_for_status()
    print(response.status_code)
    # 保存图片
    with open('image.jpg', 'wb') as f:
        f.write(response.content)
except requests.exceptions.RequestException as e:
    print("Error:", e)

方案2:关闭连接池与重试机制

强制单次连接,避免重试触发反爬:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

url = 'https://img.uefa.com/imgml/uefacom/uel/social/og-default.jpg'

# 构建不重试的适配器
adapter = HTTPAdapter(max_retries=Retry(total=0, read=False, connect=False))
session = requests.Session()
session.mount('https://', adapter)

# 设置合法UA并禁用压缩
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
    'Accept-Encoding': None
}

try:
    response = session.get(url, headers=headers, verify=False, timeout=10)
    response.raise_for_status()
    print(response.status_code)
except requests.exceptions.RequestException as e:
    print("Error:", e)

方案3:复用http.client的SSL上下文

让requests使用和http.client完全一致的SSL配置:

import requests
import ssl

url = 'https://img.uefa.com/imgml/uefacom/uel/social/og-default.jpg'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

# 使用和http.client相同的SSL上下文
ssl_context = ssl._create_unverified_context()

try:
    response = requests.get(url, headers=headers, verify=False, timeout=10, ssl=ssl_context)
    response.raise_for_status()
    print(response.status_code)
except requests.exceptions.RequestException as e:
    print("Error:", e)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:45:01