爬虫爬取网页时报错:requests.exceptions.SSLError: HTTPSConnectionPool(host=‘www.cnblogs.com‘, port=443): Max r

'# 爬虫爬取网页时报错:requests.exceptions.SSLError: HTTPSConnectionPool(host=‘www.cnblogs.com‘, port=443): Max r

一、背景与问题

在Python爬虫开发中,requests.exceptions.SSLError 是最常见的HTTPS连接错误之一。当我们尝试通过HTTPS协议爬取某些网站时,可能会遇到如下错误:

requests.exceptions.SSLError: HTTPSConnectionPool(host='www.cnblogs.com', port=443): Max retries exceeded with url

这个错误的核心原因是:爬虫在建立HTTPS连接时,SSL/TLS协议握手失败。常见原因包括:

  1. 服务器证书验证失败(证书过期、自签名证书、证书链不完整)
  2. 客户端SSL库版本过低(缺少支持现代TLS协议的实现)
  3. 网络代理配置错误
  4. 服务器端配置异常(如SSL证书与域名不匹配)

本文将深入解析该错误的原理,并提供完整的解决方案。

二、基本原理

1. HTTPS协议原理

HTTPS通过SSL/TLS协议对HTTP进行加密,其核心流程如下:

  1. 客户端发起HTTPS请求
  2. 服务器返回证书(包含公钥)
  3. 客户端验证证书有效性(CA签名、域名匹配、有效期等)
  4. 双方协商加密算法和密钥
  5. 建立加密通道进行数据传输

2. SSL证书验证机制

Python的requests库默认会验证服务器证书的以下要素:

  • 证书是否由可信CA签发
  • 证书是否在有效期内
  • 证书中的域名是否与请求的域名匹配
  • 证书链是否完整

当验证失败时会抛出SSLError异常。

三、环境准备

pip install requests

需要验证的网站:https://www.cnblogs.com(注意:该网站可能已变更HTTPS配置)

四、核心实现

1. 基础请求示例

import requests

response = requests.get('https://www.cnblogs.com')
print(response.status_code)

预期结果:返回200 OK状态码

实际结果:抛出SSLError异常

2. 处理SSL证书验证错误

方案一:忽略证书验证(不推荐生产环境使用)

import requests

response = requests.get(
    'https://www.cnblogs.com',
    verify=False  # 忽略证书验证
)
print(response.status_code)

说明:通过verify=False参数禁用证书验证,但会带来安全风险

方案二:使用本地CA证书

import requests

# 假设我们有一个本地CA证书文件 ca.crt
response = requests.get(
    'https://www.cnblogs.com',
    verify='/path/to/ca.crt'  # 指定本地CA证书路径
)
print(response.status_code)

说明:需要确保证书文件与服务器证书链匹配

3. 处理证书过期问题

import requests
from urllib3.exceptions import InsecureRequestWarning

# 禁用SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

response = requests.get(
    'https://www.cnblogs.com',
    verify=False
)
print(response.status_code)

说明:在测试环境中可临时禁用警告,生产环境应避免

五、完整案例

案例:爬取CSDN博客内容(模拟场景)

import requests
from urllib3.exceptions import InsecureRequestWarning

# 配置参数
base_url = 'https://blog.csdn.net'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
}

# 禁用SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def fetch_page(url):
    try:
        response = requests.get(url, headers=headers, verify=False, timeout=10)
        response.raise_for_status()  # 抛出HTTP错误
        return response.text
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return None

# 使用示例
content = fetch_page(f"{base_url}/xxx")
if content:
    print("成功获取页面内容")
else:
    print("获取内容失败")

关键代码解释:

  1. verify=False:临时禁用证书验证
  2. timeout=10:设置超时时间防止无限等待
  3. raise_for_status():检查HTTP响应状态码

六、源码解析

1. requests库的SSL验证流程

# requests/sessions.py 中的核心逻辑
def send(self, request, **kwargs):
    # ... 其他代码
    if self.verify is not True:
        # 当 verify=False 时跳过证书验证
        kwargs['verify'] = False
    # ... 其他代码

2. SSL证书验证逻辑

# urllib3/connection.py 中的验证逻辑
def connect(self):
    # ... 其他代码
    if self.assert_hostname:
        # 验证证书域名匹配
        if not cert_name_matches(cert, self.host):
            raise SSLCertVerificationError(...)
    # ... 其他代码

七、进阶使用

1. 使用代理服务器

proxies = {
    'https': 'https://proxy.example.com:8888'
}

response = requests.get(
    'https://www.cnblogs.com',
    proxies=proxies,
    verify=False
)

2. 使用自定义SSL上下文

import ssl

context = ssl.create_default_context()
context.check_hostname = False  # 关闭域名验证
context.verify_mode = ssl.CERT_NONE  # 关闭证书验证

response = requests.get(
    'https://www.cnblogs.com',
    verify=context
)

3. 使用连接池优化性能

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

session = requests.Session()
session.mount('https://', HTTPAdapter(max_retries=3))

八、性能与工程实践

1. 性能优化

方案说明适用场景
使用连接池复用TCP连接高频访问同一服务器
设置超时防止无限等待网络不稳定场景
并行请求多线程/异步处理大量请求场景
压缩数据减少传输体积带宽受限场景

2. 安全注意事项

  • 证书验证:务必启用证书验证(verify=True),防止中间人攻击
  • 证书更新:定期更新CA证书库(certifi包)
  • 加密算法:优先使用TLSv1.2及以上协议
  • 证书匹配:确保证书域名与请求域名完全匹配(包括子域名)

3. 异常处理

try:
    response = requests.get(url, timeout=5)
except requests.exceptions.SSLError as e:
    print(f"SSL错误: {e}")
except requests.exceptions.Timeout:
    print("请求超时")
except requests.exceptions.RequestException as e:
    print(f"其他错误: {e}")

九、常见问题与踩坑

1. 常见错误及解决方案

问题原因解决方案
证书过期服务器证书未及时更新联系服务器管理员
自签名证书证书未被CA签名使用verify=False临时处理
域名不匹配证书域名与请求域名不一致检查域名拼写
协议版本不兼容服务器使用旧版TLS升级客户端SSL库

2. 常见陷阱

  • 忽略证书验证的隐患:可能导致中间人攻击(MITM)
  • 证书链不完整:需要包含所有中间证书
  • SSLv3协议不安全:需强制使用TLSv1.2及以上版本

十、最佳实践

1. 推荐方案

  1. 优先启用证书验证(verify=True)
  2. 使用最新版requests库(确保支持现代TLS协议)
  3. 配置合理的超时时间(建议5-10秒)
  4. 使用代理时配置验证(防止代理服务器劫持流量)

2. 不推荐方案

  1. 在生产环境使用verify=False
  2. 使用过期的CA证书库
  3. 不处理SSL协议版本
  4. 忽略证书域名匹配检查

十一、总结

requests.exceptions.SSLError 错误本质上是HTTPS协议安全机制的正常反馈,而非程序错误。在爬虫开发中,我们需要理解SSL/TLS协议的工作原理,正确配置证书验证,同时权衡安全性和功能性需求。

建议在实际项目中:

  • 开发阶段:启用证书验证,确保安全性
  • 测试阶段:可临时禁用验证进行调试
  • 生产环境:严格配置证书验证,防止中间人攻击

通过合理配置SSL参数、处理证书验证、优化连接管理,可以有效解决SSL相关错误,同时保证爬虫系统的安全性和稳定性。

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日