Python中requests库在并发太高的情况下报错如何解决
也就开了 32 个线程这样,爬一会就疯狂报错 然后把并发改为 10 之后就可以正常爬了
requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)
还有个问题:爬虫插入 mysql 的策略是什么? 一定数量批量插 还是一条一条插 感觉一条条插在高并发的情况下十分不稳定
Python中requests库在并发太高的情况下报错如何解决
8 回复
貌似是 openssl 的限制?
帖子标题问的是requests库在高并发下报错怎么搞。这个我熟,直接上代码。
核心就两点:一是用连接池复用TCP连接,别每次都新建;二是控制并发数,别一股脑发一堆请求把服务器或自己搞崩了。用requests.Session()配合requests.adapters.HTTPAdapter来调连接池参数,再用concurrent.futures的ThreadPoolExecutor来限制线程数,稳得很。
下面是个完整例子,直接抄了改改就能用:
import requests
from requests.adapters import HTTPAdapter
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib3.util.retry import Retry
# 1. 创建自定义Session,配置连接池和重试策略
session = requests.Session()
# 设置重试策略(可选,但建议加上)
retry_strategy = Retry(
total=3, # 总重试次数
backoff_factor=1, # 退避因子
status_forcelist=[429, 500, 502, 503, 504], # 遇到这些状态码就重试
)
adapter = HTTPAdapter(
pool_connections=100, # 连接池大小
pool_maxsize=100, # 最大连接数
max_retries=retry_strategy,
)
session.mount('http://', adapter)
session.mount('https://', adapter)
# 2. 要请求的URL列表
urls = [
'https://httpbin.org/get?id=1',
'https://httpbin.org/get?id=2',
# ... 你的URL列表,可以有几百上千个
]
# 3. 实际的请求函数
def fetch_url(url):
try:
# 使用配置好的session,而不是requests.get
response = session.get(url, timeout=5)
# 可以根据需要处理响应,这里简单返回状态码和内容长度
return url, response.status_code, len(response.content)
except Exception as e:
return url, f'ERROR: {e}', None
# 4. 使用线程池控制并发数
def main():
results = []
# 关键在这里:max_workers控制最大并发线程数,别设太高,比如10-50
with ThreadPoolExecutor(max_workers=20) as executor:
# 提交所有任务
future_to_url = {executor.submit(fetch_url, url): url for url in urls}
# 获取完成的结果
for future in as_completed(future_to_url):
result = future.result()
results.append(result)
print(f'Completed: {result[0]} -> {result[1]}')
# 处理结果...
print(f"\nTotal requests: {len(urls)}")
print(f"Successful: {len([r for r in results if 'ERROR' not in str(r[1])])}")
if __name__ == '__main__':
main()
重点解释:
HTTPAdapter:pool_connections和pool_maxsize设大点,让连接能复用。max_retries用Retry对象配置,自动处理429、500这些临时错误。ThreadPoolExecutor(max_workers=20):这是控制并发数的阀门。别瞎设成500,根据你机器和对方服务器的承受能力来,一般20-100够用了。线程太多会吃光资源,报各种连接错误。- 一定要用
Session:整个程序就用一个session实例,所有请求都通过它发,连接池才能生效。 - 超时:
timeout=5必须加,防止某些请求卡死拖垮整个程序。
如果请求量巨大(比如上万),可以考虑用asyncio + aiohttp,那才是为高并发而生的。但requests同步写法简单,加上面这套配置,应对日常几百几千的并发压力不大。
简单说就是调大连接池,用Session,控制好线程数。
批量插
pip install ‘requests[security]’
后来我发现 我开并发为 10 的情况下也会报错
试试异步 aiohttp
你好,我也遇到这个问题。请问解决了吗?
安装 requets[security]

