📌 摘要
初学爬虫最头疼的问题:单线程循环爬取速度极慢,几十条数据就要等待几十秒。很多同学只会写 for 循环串行请求,完全没有并发思维。
本文详细讲解 ThreadPoolExecutor 线程池 在爬虫中的实战用法,带你从慢速单线程升级为高并发多线程爬取。文章包含原理对比、完整可运行代码、线程数量优化、异常捕获、高频踩坑总结,零基础可直接上手,大幅提升爬虫采集效率。
关键词:Python爬虫、线程池、ThreadPoolExecutor、爬虫提速、并发爬虫、多线程实战
一、前言:为什么你的爬虫速度很慢?
绝大多数新手爬虫代码长这样:for 循环逐条请求、逐条等待响应。
网页请求属于 IO 密集型任务,网络等待时间远远大于代码执行时间。单线程模式下,CPU 大量时间处于空闲等待状态,资源严重浪费。
合规声明:本文技术仅用于公开合规数据采集与技术学习,请勿用于批量违规爬取、侵权采集等场景。
二、单线程 VS 多线程爬虫速度对比
2.1 单线程爬虫(低效,不推荐)
串行执行,必须等待上一个请求完成,才会执行下一个,耗时最长。
2.2 线程池爬虫(高效,推荐)
一次性开启固定数量线程,并发处理多个请求,IO 等待期间自动切换任务,效率提升 5~20 倍。
三、线程池核心原理(通俗讲解)
ThreadPoolExecutor 采用 任务队列 + 线程复用 机制:
-
提前创建固定数量线程,不会频繁创建销毁线程,节省资源
-
任务自动分配,空闲线程自动承接新任务
-
自动管理并发数量,防止请求风暴
相比手动创建 Thread,线程池更稳定、代码更简洁、可维护性更强。
四、环境依赖
线程池为 Python 内置库,无需额外安装,只需安装请求库即可:
pip install requests
五、完整实战代码:线程池爬虫(可直接上线)
包含:请求头伪装、超时处理、异常捕获、线程池并发控制、批量采集
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
# 全局请求头
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/128.0.0.0 Safari/537.36"
}
# 并发线程数,根据网站抗压能力调整
MAX_WORKERS = 10
def crawl_url(url):
"""单页面请求函数"""
try:
res = requests.get(url, headers=HEADERS, timeout=10)
res.encoding = res.apparent_encoding
return {"url": url, "status": res.status_code, "len": len(res.text)}
except Exception as e:
return {"url": url, "error": str(e)}
def batch_crawl(url_list):
"""线程池批量采集"""
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
# 提交所有任务
future_task = [executor.submit(crawl_url, url) for url in url_list]
# 遍历结果
for future in as_completed(future_task):
result = future.result()
if "error" in result:
print(f"❌ 失败:{result['url']},原因:{result['error']}")
else:
print(f"✅ 成功:{result['url']},状态码:{result['status']},页面大小:{result['len']}")
if __name__ == "__main__":
# 测试链接列表
test_urls = [f"https://httpbin.org/get?num={i}" for i in range(20)]
batch_crawl(test_urls)
六、核心代码详解
6.1 max_workers 并发数设置(关键)
-
学习测试:10~20
-
常规网站:5~10
-
防护严格网站:2~5
切勿设置过大,瞬间高并发会触发网站限流与拦截。
谁先执行完成,谁先返回结果,不用等待所有任务结束,采集效率更高。
七、生产环境高频踩坑总结
坑1:线程数设置过大
盲目开几十上百线程,导致大量请求失败、连接超时、被网站限流。
坑2:线程内不做异常捕获
单条请求报错直接导致整个线程崩溃,批量任务中断。必须单独 try-except 捕获异常。
坑3:并发请求无间隔
纯高速并发特征过于明显,容易被识别为程序批量请求,建议适量控制并发数。
坑4:混用同步阻塞代码
线程池内部不要加入大量耗时计算,线程池只适合 IO 密集型任务。
八、线程池 VS 异步协程 选型建议
-
中小型爬虫、快速开发、稳定优先 → 推荐 ThreadPoolExecutor 线程池
-
超大规模、上万级并发、极致速度 → 推荐 asyncio 异步协程
九、总结
对于绝大多数爬虫开发场景,线程池是性价比最高的提速方案。几乎零学习成本、无需重构代码,即可让爬虫效率提升数倍甚至数十倍。