Python Requests访问basketball-reference.com遭遇SSL版本错误的技术求助
解决SSL错误[SSL: WRONG_VERSION_NUMBER]及排查指引
兄弟,我之前批量爬取体育数据的时候也碰到过这个随机蹦出来的SSL版本错误,太闹心了!给你梳理下问题的可能原因、排查步骤,还有SSL知识的学习思路:
一、错误成因的初步判断
[SSL: WRONG_VERSION_NUMBER]本质是SSL/TLS握手阶段版本协商失败,简单说就是你的请求用的SSL协议版本,和服务器要求的版本不匹配,或者网络中间环节(比如代理、防火墙)篡改了握手包。随机出现的原因大概率是批量请求时,连接复用、网络波动或者服务器临时的反爬策略导致部分请求的握手流程异常。
二、具体排查步骤
1. 先修复代码里的小bug
你代码里写的allow_redirects='False'是字符串类型,但requests要求这个参数是布尔值!字符串'False'会被Python当成True处理,这可能导致部分请求意外重定向,间接引发SSL异常。赶紧改成:
search_results_page = requests.get(url, allow_redirects=False)
2. 升级依赖库版本
旧版的requests和urllib3对新的TLS协议(比如TLSv1.3)支持不好,或者存在兼容性bug,先升级到最新版:
pip install --upgrade requests urllib3
3. 强制指定SSL协议版本
手动指定用TLSv1.2或TLSv1.3发起请求,避免自动协商时出现版本不匹配。可以自定义一个HTTP适配器,绑定到requests会话上:
import ssl import time import requests from bs4 import BeautifulSoup as bs from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager from urllib3.util import ssl_ # 自定义适配器,强制使用TLSv1.2 class TLSAdapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=False): # 创建指定TLS版本的上下文 ctx = ssl_.create_urllib3_context(ssl.PROTOCOL_TLSv1_2) self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, ssl_context=ctx) # 全局创建一个会话,复用连接 session = requests.Session() session.mount('https://', TLSAdapter()) nightmare = { 'Bol Bol': 'bolbo01', 'Nicolo Melli': 'mellini01', 'Davis Bertans': 'bertada01', 'Tomas Satoransky': 'satorto01', 'Theo Maledon': 'maledth01', 'Bogdan Bogdanovic': 'bogdabo01', } def get_bref_id(full_name): time.sleep(0.5) # 适当延长间隔,降低服务器压力 if full_name not in nightmare: try: first_name, last_name = full_name.split(' ') url = f'https://www.basketball-reference.com/search/search.fcgi?search={first_name}+{last_name}' # 使用session.get代替requests.get,复用自定义SSL配置 search_results_page = session.get(url, allow_redirects=False) soup = bs(search_results_page.content, 'html.parser') potential_links = soup.find_all('div', class_="search-item-name") bucket = [element for element in potential_links if '202' in element.text and first_name in element.text] bref_id = str(bucket[0]).replace('.', '/').split('/')[3] except IndexError: # 处理直接跳转到球员页面的情况 bref_id = search_results_page.url.split('/')[5].split('.')[0] finally: return bref_id else: return nightmare[full_name]
4. 检查网络环境
如果是在公司、学校等受限网络环境下,防火墙或代理可能会拦截或篡改SSL握手包。试试切换到个人热点或者无代理的网络,看错误是否消失。
5. 调整请求间隔
你现在的sleep(0.2)间隔有点短,批量请求太频繁可能触发服务器的反爬机制,导致服务器返回异常的SSL响应。可以延长到0.5-1秒,降低被限制的概率。
三、SSL知识学习路径
从入门到实战,循序渐进:
- 入门阶段:先搞懂SSL/TLS的核心作用(加密通信、身份验证),理解握手流程的基本步骤——客户端发版本问候、服务器返回支持的版本和证书、双方协商密钥。这个错误就是握手时版本协商不通过导致的。
- 进阶阶段:学习Python标准库
ssl模块的基本用法,了解ssl.SSLContext的作用,以及如何配置协议版本、证书验证等。 - 实战阶段:查看requests官方文档的SSL相关章节,理解会话(Session)、连接池对SSL连接的影响,学会自定义适配器解决兼容性问题。
内容的提问来源于stack exchange,提问作者pphotsauce
相关产品推荐
相关产品推荐

