Python爬虫效率优化:单线程、多线程、多进程与协程性能对比
本文通过实测对比单线程、多线程、多进程及aiohttp协程四种方式在Python爬虫中的表现。结果显示,处理十万级页面时,aiohttp协程方案比单线程快90倍,多线程提升68倍,多进程提升7倍。文章提供了各方案的代码实现与耗时数据,为提升爬虫并发效率提供实用参考。

文 | 闲欢
来源:Python 技术「ID: pythonall」
今日浏览知乎时,留意到一个颇具探讨价值的问题:如何有效优化 Python 爬虫的运行速度?
该问题的具体描述如下:
目前正在进行一个 Python 爬虫项目的开发,使用单线程 urllib 库发现处理速度过于缓慢,无法满足十万级页面的数据抓取需求。恳请有经验的朋友分享提升爬取效率的有效方法。
此问题虽受到较多关注,但实际给出详细解答的回复并不多。
鉴于此,笔者决定尝试对此问题进行深入分析与解答。
程序性能优化的核心思路通常有两类:一是通过并发机制提升单位时间内的任务处理量;二是从程序底层逻辑寻找提效点,例如采用 gzip 压缩传输数据、优化数据处理算法等。
接下来,我将分别演示几种常见的并发处理方式,并对比它们执行相同任务时的效率差异。
基础版爬虫实现
首先,我们构建一个基础的爬虫程序,以评估单线程模式下的处理耗时。
import time
import requests
from datetime import datetime
def fetch(url):
r = requests.get(url)
print(r.text)
start = datetime.now()
t1 = time.time()
for i in range(100):
fetch('http://httpbin.org/get')
print('requests版爬虫耗时:', time.time() - t1)
# requests版爬虫耗时:54.86306357383728
借助专用的爬虫测试网站进行实验,模拟抓取 100 次请求,实测总耗时为 54.86 秒。
多线程版爬虫实现
随后,我们将上述程序重构为多线程版本:
import threading
import time
import requests
def fetch():
r = requests.get('http://httpbin.org/get')
print(r.text)
t1 = time.time()
t_list = []
for i in range(100):
t = threading.Thread(target=fetch, args=())
t_list.append(t)
t.start()
for t in t_list:
t.join()
print("多线程版爬虫耗时:", time.time() - t1)
# 多线程版爬虫耗时:0.8038511276245117
数据显示,启用多线程后,运行速度提升了 68 倍。由于并发执行特性,抓取 100 次请求的总耗时与单次请求耗时基本相当。需注意的是,这仅为简化示例,实际应用中线程数量受系统资源限制,不可无限增加。
多进程版爬虫实现
除多线程外,利用多进程机制同样能有效提升爬虫速度:
import requests
import time
import multiprocessing
from multiprocessing import Pool
MAX_WORKER_NUM = multiprocessing.cpu_count()
def fetch():
r = requests.get('http://httpbin.org/get')
print(r.text)
if __name__ == '__main__':
t1 = time.time()
p = Pool(MAX_WORKER_NUM)
for i in range(100):
p.apply_async(fetch, args=())
p.close()
p.join()
print('多进程爬虫耗时:', time.time() - t1)
多进程爬虫耗时: 7.9846765995025635
对比结果可见,多进程处理耗时约为多线程的 10 倍,相较于单线程版本,速度提升了 7 倍。
协程版爬虫实现
我们将程序调整为使用 aiohttp 库来实现异步操作,以观察其效率表现:
import aiohttp
import asyncio
import time
async def fetch(client):
async with client.get('http://httpbin.org/get') as resp:
assert resp.status == 200
return await resp.text()
async def main():
async with aiohttp.ClientSession() as client:
html = await fetch(client)
print(html)
loop = asyncio.get_event_loop()
tasks = []
for i in range(100):
task = loop.create_task(main())
tasks.append(task)
t1 = time.time()
loop.run_until_complete(main())
print("aiohttp版爬虫耗时:", time.time() - t1)
aiohttp版爬虫耗时: 0.6133313179016113
结果显示,采用该方式实现的爬虫,相比单线程版本速度提升了 90 倍,且性能优于多线程方案。
总结分析
通过上述程序对比实验,针对多任务爬虫场景,多线程、多进程及协程三种方式的效率排序为:aiohttp > 多线程 > 多进程。因此,对于轻量级爬虫任务,若追求高效处理,协程是优选方案。但需注意,此处仅为基础示例,实际工程中通常建议结合线程池、进程池或协程池进行资源管理。
这是否即为最终答案?
对于严谨的开发者而言,答案并非如此绝对。实际上,还存在如 grequests 等优化库,可从请求层面解决并发问题。在实际处理流程中,必然存在其他优化空间,本文仅从最常见的几种并发模式进行对比,旨在应对基础爬虫场景。其他高效方案欢迎在评论区留言交流探讨。
以上即为关于“Python爬虫效率如何提高”的详细解析,更多提升 Python 爬虫效率的技术资料,敬请关注本站后续发布的相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













