使用requests+Beautiful Soup爬取PyPI时请求挂起的排查
我来分享几个实用的排查步骤,帮你解决PyPI请求挂起的问题——之前爬取类似站点时也遇到过类似的坑,一步步来:
1. 先修正请求协议:改用HTTPS
你当前用的是http://pypi.org,但现在PyPI已经强制启用HTTPS了,HTTP请求会被重定向到HTTPS,但这个重定向过程可能因为协议兼容问题导致请求卡住。先把URL改成https://pypi.org试试,这是最常见的触发点。
2. 简化请求头,逐步排查
你复制的浏览器请求头包含很多浏览器特有的字段(比如sec-ch-ua系列、dnt、sec-fetch-*),这些字段可能会被PyPI的服务器识别为异常请求,反而导致请求被挂起。先从最小化的请求头开始测试:
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54' }
只保留User-Agent,测试能不能正常请求。如果没问题,再逐个添加之前的请求头字段,每次加一个就测试一次,这样就能定位到哪个字段导致了问题。
3. 给请求添加超时限制
无限挂起很难排查原因,给get方法加上timeout参数,比如设置10秒超时:
response = session.get("https://pypi.org", headers=headers, timeout=10)
这样如果请求超时,会抛出明确的异常(比如requests.exceptions.ReadTimeout或ConnectionTimeout),能帮你判断是连接阶段卡住还是服务器迟迟不返回响应。
4. 临时跳过Session,直接用requests.get测试
虽然Session能管理Cookie,但有时候Session的默认配置可能有隐藏问题。试试不用Session,直接发送请求:
import requests headers = {'User-Agent': '你的UA字符串'} response = requests.get("https://pypi.org", headers=headers, timeout=10) print(response.status_code)
如果这个请求能正常返回,那问题可能出在Session的某些配置上(比如虽然设置了trust_env=False,但Session还是继承了某些系统代理?)。
5. 开启调试日志,查看请求全流程
开启requests的调试日志,能看到请求从DNS解析到接收响应的每一步细节,帮你定位卡住的环节:
import logging import requests # 配置日志 logging.basicConfig(level=logging.DEBUG) urllib3_log = logging.getLogger("requests.packages.urllib3") urllib3_log.setLevel(logging.DEBUG) urllib3_log.propagate = True # 执行请求 session = requests.Session() session.trust_env = False response = session.get("https://pypi.org", headers=headers, timeout=10)
查看日志输出,你能看到类似DEBUG:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): pypi.org:443这样的信息,跟踪到请求卡在了哪个阶段(比如连接建立、发送请求、读取响应)。
6. 检查是否触发反爬机制
PyPI有基础的反爬策略,比如频繁请求会被限流,但你是单次请求就挂起,可能性稍低。不过可以试试在请求前先访问https://pypi.org/robots.txt,确保你的爬取行为符合规则,或者稍微增加一点请求间隔(虽然单次请求不需要)。
先从前面几个步骤开始排查,尤其是HTTPS和简化请求头,大概率能解决问题。
内容的提问来源于stack exchange,提问作者Sterling Butters

