threadpoolexecutor 在爬虫中慢是因为cpu密集型操作触发gil锁死,应只用于纯网络请求;含解析的混合任务需用processpoolexecutor绕过gil,配合requests.session独立初始化或httpx,必要时结合asyncio发请求+进程池解析。

ThreadPoolExecutor 在爬虫里跑得慢,不是代码写错了,而是你让它干了它不擅长的事——别让线程去算质数、解析大HTML、做正则匹配,这些CPU密集型操作一塞进去,GIL 就立刻锁死所有线程,4个线程可能比1个还慢。
真正该做的,是把任务拆开:网络请求归网络请求,计算归计算,各走各的路。
什么时候多线程依然够用?
纯网络请求场景下,ThreadPoolExecutor 依然高效,因为 GIL 会在 requests.get() 等阻塞调用时自动释放。
- 典型表现:top 看到 CPU 占用率始终在 100% 以下,但整体耗时明显下降
- 适用任务:
requests/urllib发请求、等待响应、读取响应体 - 不适用任务:拿到响应后立刻用
BeautifulSoup解析 10MB HTML、用re.findall()扫描长文本、做 JSON 嵌套转换 - 线程数建议设为
os.cpu_count() * 2左右,超过 20–30 通常收益递减,反而增加上下文切换开销
为什么 multiprocessing.ProcessPoolExecutor 是更稳的选择?
当你的爬虫流程包含大量本地计算(比如批量清洗、格式标准化、XPath 提取、Pandas 转换),ProcessPoolExecutor 能彻底绕过 GIL,每个进程独占一个 CPU 核心。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 必须加
if __name__ == "__main__":保护,否则 Windows/macOS 上会反复 fork 子进程 - 参数传递尽量用
int、str、tuple这类不可变类型;传dict或自定义类会触发 pickle 序列化,慢且可能失败 - 不要在子进程中再开线程池——进程内再并发没意义,还容易触发资源竞争
- 实测中,含解析的混合任务(请求+BS4+正则)用 4 进程比 4 线程快 2.3 倍以上,且 CPU 利用率接近 400%
requests + ProcessPoolExecutor 组合怎么写才不踩坑?
直接把 requests.get() 放进 ProcessPoolExecutor 会出错,因为 requests 内部状态(如连接池)不能跨进程共享。
- 正确做法:每个进程里独立初始化
requests.Session(),或改用无状态的httpx(支持异步/同步双模式) - 避免全局变量:不要在模块顶层定义
session = requests.Session(),子进程看不到它 - 示例结构:
def fetch_and_parse(url):
# 每个进程自己建 session
with requests.Session() as s:
resp = s.get(url, timeout=10)
# 此处做解析、清洗等 CPU 密集操作
return len(resp.text)
<p>if <strong>name</strong> == "<strong>main</strong>":
urls = [...]
with ProcessPoolExecutor(max_workers=4) as exe:
results = list(exe.map(fetch_and_parse, urls))</p>
要不要上 asyncio?看你的瓶颈在哪
asyncio + aiohttp 是纯 IO 密集型爬虫的天花板方案,但它不解决 CPU 瓶颈——如果你的瓶颈在解析,asyncio 只会让 CPU 更忙。
- 适合场景:万级 URL、响应体小、解析逻辑极轻(比如只取
<title></title>) - 不适合场景:每个页面要跑 5 层嵌套 XPath、生成 PDF、OCR 文字识别
- 混合用法更现实:用
asyncio并发发请求,把返回结果丢给ProcessPoolExecutor处理——这才是工程里真正跑得起来的组合
真正的难点不在选哪个模块,而在切分任务边界:哪些操作必须在进程里做,哪些可以在线程里做,哪些干脆交给 C 扩展。很多性能问题,其实卡在“把所有事都堆在一个函数里”这一步。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










