京公网安备 11010802034615号
经营许可证编号:京B2-20210330
作者:闲欢
来源:Python 技术
今天在浏览知乎时,发现一个有趣的问题:
如何优化 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,可以从请求上解决并发问题。实际的处理过程中,肯定还有其他的优化点,这里只是从最常见的几种并发方式去比较而已,应付简单爬虫还是可以的,其他的方式欢迎大家在评论区留言探讨。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在存量竞争时代,用户流失率直接影响企业的营收与市场竞争力。无论是电商、互联网服务还是金融行业,提前精准预测潜在流失用户, ...
2026-01-09在量化投资领域,多因子选股是主流的选股策略之一——其核心逻辑是通过挖掘影响股票未来收益的各类因子(如估值、成长、盈利、流 ...
2026-01-09在CDA(Certified Data Analyst)数据分析师的工作场景中,分类型变量的关联分析是高频需求——例如“用户性别与商品偏好是否相 ...
2026-01-09数据库中的历史数据,是企业运营过程中沉淀的核心资产——包含用户行为轨迹、业务交易记录、产品迭代日志、市场活动效果等多维度 ...
2026-01-08在电商行业竞争日趋激烈的当下,数据已成为驱动业务增长的核心引擎。电商公司的数据分析师,不仅是数据的“解读官”,更是业务的 ...
2026-01-08在数据驱动决策的链路中,统计制图是CDA(Certified Data Analyst)数据分析师将抽象数据转化为直观洞察的关键载体。不同于普通 ...
2026-01-08在主成分分析(PCA)的学习与实践中,“主成分载荷矩阵”和“成分矩阵”是两个高频出现但极易混淆的核心概念。两者均是主成分分 ...
2026-01-07在教学管理、学生成绩分析场景中,成绩分布图是直观呈现成绩分布规律的核心工具——通过图表能快速看出成绩集中区间、高分/低分 ...
2026-01-07在数据分析师的工作闭环中,数据探索与统计分析是连接原始数据与业务洞察的关键环节。CDA(Certified Data Analyst)作为具备专 ...
2026-01-07在数据处理与可视化场景中,将Python分析后的结果导出为Excel文件是高频需求。而通过设置单元格颜色,能让Excel中的数据更具层次 ...
2026-01-06在企业运营、业务监控、数据分析等场景中,指标波动是常态——无论是日营收的突然下滑、用户活跃度的骤升,还是产品故障率的异常 ...
2026-01-06在数据驱动的建模与分析场景中,“数据决定上限,特征决定下限”已成为行业共识。原始数据经过采集、清洗后,往往难以直接支撑模 ...
2026-01-06在Python文件操作场景中,批量处理文件、遍历目录树是高频需求——无论是统计某文件夹下的文件数量、筛选特定类型文件,还是批量 ...
2026-01-05在神经网络模型训练过程中,开发者最担心的问题之一,莫过于“训练误差突然增大”——前几轮还平稳下降的损失值(Loss),突然在 ...
2026-01-05在数据驱动的业务场景中,“垃圾数据进,垃圾结果出”是永恒的警示。企业收集的数据往往存在缺失、异常、重复、格式混乱等问题, ...
2026-01-05在数字化时代,用户行为数据已成为企业的核心资产之一。从用户打开APP的首次点击,到浏览页面的停留时长,再到最终的购买决策、 ...
2026-01-04在数据分析领域,数据稳定性是衡量数据质量的核心维度之一,直接决定了分析结果的可靠性与决策价值。稳定的数据能反映事物的固有 ...
2026-01-04在CDA(Certified Data Analyst)数据分析师的工作链路中,数据读取是连接原始数据与后续分析的关键桥梁。如果说数据采集是“获 ...
2026-01-04尊敬的考生: 您好! 我们诚挚通知您,CDA Level III 考试大纲将于 2025 年 12 月 31 日实施重大更新,并正式启用,2026年3月考 ...
2025-12-31“字如其人”的传统认知,让不少“手残党”在需要签名的场景中倍感尴尬——商务签约时的签名歪歪扭扭,朋友聚会的签名墙不敢落笔 ...
2025-12-31