如果您按GB支付代理流量,那么无头浏览器和普通HTTP客户端之间的差异可能会使您在同一数据集(1000个页面)上花费多达15-20倍的费用。在本文中,我们将提供Playwright、Puppeteer和Python库requests的实际流量消耗测量、测试代码以及在不损失内容的情况下减少数据量的有效方法。
为什么流量消耗对爬虫至关重要
大多数代理提供商,包括住宅和移动池,按GB计费,而不是按请求数量。这意味着您用于爬取网站的工具直接影响项目预算。无头浏览器会完整加载页面:HTML、CSS、JavaScript、图像、字体、分析脚本、广告横幅和跟踪器。而像requests这样的HTTP客户端只下载您明确请求的内容——通常是纯HTML文档。
在规模上,这种差异尤其明显。如果您在Wildberries或Ozon上抓取商品卡片,收集竞争对手的价格或监控Google的搜索结果,1000个页面的量是一个脚本的典型日常标准。在每月处理数十万个页面时,流量节省成为一项显著的开支,尤其是当使用住宅代理时,GB的成本高于数据中心代理。
额外的复杂性在于,现代网站积极防止机器人:检查JavaScript渲染、鼠标行为、canvas指纹。这迫使开发人员从简单的HTTP请求转向像Playwright或Puppeteer这样的完整浏览器,这些工具在流量上占用更多。了解确切的数字有助于提前计算代理预算并选择适合特定任务的正确工具。
流量测量方法
为了进行公平比较,我使用了相同的1000个URL列表——中等复杂度的商品卡片,包含图像、分析脚本和几个第三方小部件(典型的电子商务网站结构)。流量测量通过系统网络监控和每个工具中内置的请求日志记录工具进行。
实验的重要条件:
- 浏览器缓存已禁用——每个页面都从“零”加载,就像通过不同IP的代理轮换工作时那样
- 所有浏览器测试均启用无头模式——这也是大多数生产脚本的工作方式
- 在基本场景中没有资源阻塞——以展示“纯”消耗而不进行优化
- 所有三个工具使用相同的网络和相同的页面集
这种方法提供了可比较的数字,可以应用于您自己的案例——将其乘以项目中的页面数量并除以代理的计费量。
requests:最低流量消耗
Python中的requests库仅下载HTTP响应的主体——您明确请求的内容。没有JavaScript,没有图像,没有对CDN的额外请求。在我的测试中,电子商务商品的平均HTML页面大小约为180-250 KB的未压缩HTML。
import requests
proxies = {
"http": "http://user:pass@proxy_host:port",
"https": "http://user:pass@proxy_host:port",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
total_bytes = 0
urls = load_urls_from_file("urls.txt") # 1000个链接的列表
for url in urls:
response = requests.get(url, headers=headers, proxies=proxies, timeout=15)
total_bytes += len(response.content)
print(f"总共下载:{total_bytes / 1024 / 1024:.2f} MB")
在1000个页面上,最终消耗为190-230 MB——即少于0.25 GB。这是最经济的选择,但它有一个关键限制:如果网站通过JavaScript(React、Vue、动态加载价格)渲染内容,requests将获得一个空的页面框架,而没有所需的数据。对于静态HTML或具有SSR的网站,这是流量与结果的理想选择。
Puppeteer:无头Chrome的流量
Puppeteer控制真实的Chromium引擎,因此会完整加载页面:HTML、CSS、字体、图像、跟踪脚本、广告iframe。即使在无头模式下,浏览器也会执行普通用户在Chrome中执行的所有网络请求。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--proxy-server=http://proxy_host:port']
});
const page = await browser.newPage();
await page.authenticate({ username: 'user', password: 'pass' });
let totalBytes = 0;
page.on('response', async (response) => {
try {
const buffer = await response.buffer();
totalBytes += buffer.length;
} catch (e) {}
});
const urls = require('./urls.json'); // 1000个链接
for (const url of urls) {
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
}
console.log(`总流量:${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
await browser.close();
})();
在我的测试中,通过Puppeteer加载的每个页面的平均大小为2.8-4.5 MB,具体取决于图像和第三方脚本的数量。在1000个页面上,这导致了3.1-4.2 GB——比requests多15-18倍。流量的主要部分来自图像(通常占页面重量的40-55%)和第三方分析、广告和聊天小部件的脚本(20-30%)。
Playwright:不同浏览器的流量
Playwright的工作方式类似,但支持三种引擎——Chromium、Firefox和WebKit。它们之间的流量消耗不同:WebKit在无头模式下由于不同的媒体内容处理方式通常稍微节省,而Firefox有时由于请求之间资源缓存的差异而加载更多数据。
from playwright.sync_api import sync_playwright
total_bytes = 0
def handle_response(response):
global total_bytes
try:
body = response.body()
total_bytes += len(body)
except Exception:
pass
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={"server": "http://proxy_host:port", "username": "user", "password": "pass"}
)
page = browser.new_page()
page.on("response", handle_response)
urls = load_urls_from_file("urls.txt")
for url in urls:
page.goto(url, wait_until="networkidle", timeout=30000)
print(f"总流量:{total_bytes / 1024 / 1024:.2f} MB")
browser.close()
在Chromium上通过Playwright的结果接近Puppeteer——在1000个页面上为2.9-4.3 GB,这是合乎逻辑的,因为这两个工具使用相同的引擎。在WebKit上,消耗低10-15%,约为2.6-3.7 GB,而在Firefox上则稍高,约为3.3-4.6 GB。这种差异可以通过每个浏览器引擎在处理字体、解码图像和网络堆栈行为方面的不同来解释。
比较表:每1000个页面的GB
以下是所有测试选项的汇总表,数字四舍五入到实用范围。这些数字适用于具有图像和典型第三方脚本集的中等电子商务页面——在新闻网站或带视频的着陆页上,消耗将更高。
| 工具 | 每1000个页面的流量 | JS渲染 | 绕过机器人检测 |
|---|---|---|---|
| requests (Python) | 0.19-0.23 GB | 否 | 弱 |
| Playwright (WebKit) | 2.6-3.7 GB | 是 | 中等 |
| Puppeteer (Chromium) | 3.1-4.2 GB | 是 | 中等 |
| Playwright (Chromium) | 2.9-4.3 GB | 是 | 良好 |
| Playwright (Firefox) | 3.3-4.6 GB | 是 | 中等 |
关键结论:如果网站不需要JavaScript渲染来获取所需数据,requests在流量上比任何浏览器解决方案节省15-20倍。但如果内容是动态加载的,或者网站积极检查浏览器行为——您将不得不为浏览器渲染流量付费。
如何将流量消耗减少5-10倍
即使您需要一个完整的浏览器,也可以在不失去所需数据的情况下显著减少流量消耗。以下是我在相同的1000个页面集上验证的有效技巧。
1. 阻止图像、字体和媒体。 图像通常占页面重量的一半以上,而在解析文本数据时它们并不需要。
await page.route('**/*', (route) => {
const type = route.request().resourceType();
if (['image', 'font', 'media'].includes(type)) {
route.abort();
} else {
route.continue();
}
});
这个技巧在Playwright和Puppeteer中都有效,能够在不损失HTML和文本数据的情况下减少40-60%的流量。
2. 阻止第三方域。 广告网络、分析、聊天小部件加载自己的脚本和图像,这些都是您不需要的。可以按域过滤请求,仅保留主要资源及其CDN。
3. 使用“domcontentloaded”代替“networkidle”。 等待网络完全加载会使浏览器等待所有后台请求,包括分析和延迟加载。如果数据在DOM中提前出现——切换到更早的事件可以加快解析并减少多余的加载。
4. 在请求之间缓存静态资源。 如果网站在所有页面上使用相同的CSS/JS文件,启用浏览器缓存(与我们测试的条件不同)在顺序遍历大量同一域的URL时可以节省大量流量。
5. 混合方法。 许多团队首先尝试requests,只有在数据不足时才切换到通过Playwright或Puppeteer访问特定页面。这结合了低基础流量消耗与在真正需要的地方进行渲染的能力。
通过合理的资源阻止,Puppeteer和Playwright的流量消耗从3-4 GB减少到0.6-1.2 GB每1000个页面——与requests相比,差异明显缩小,同时仍保持与JS渲染和反机器人保护的兼容性。
如何根据流量选择代理
流量计算直接影响代理类型的选择。对于通过requests在静态网站上进行轻量HTTP请求,数据中心代理非常合适——它们速度快、流量便宜,并且足够使用,如果网站不检查行为信号。
如果任务需要通过Playwright或Puppeteer进行完整渲染以绕过反机器人系统——例如,在市场上收集价格或监控搜索引擎结果——使用住宅代理更为合理。它们因IP声誉而被阻止的可能性较小,这在每个请求“重量”达到几兆字节时至关重要,因为由于阻止而重复获取数据的成本很高。
对于特别严格检查IP和用户代理匹配的网站(银行服务、具有移动验证的应用程序),值得考虑移动代理——尽管流量成本更高,但它们提供最大的IP地址信任度,并最小化因封禁而导致的重复请求数量。
实际指导:根据公式“单个页面的重量×页面数量×因错误和封禁的重复系数”计算流量,并将最终的GB与提供商的费率进行比较。上述资源优化通常会带来比选择更便宜的代理类型更多的节省——但正确工具与正确代理的组合可以产生最大的效果。
结论
requests仍然是流量最经济的工具——每1000个页面约0.2 GB,但不适用于动态内容的网站。Puppeteer和Playwright提供完整的渲染和更好的保护绕过,但流量消耗增加到3-4.5 GB,针对同样的1000个页面。阻止图像、字体和第三方域将这一差距缩小到3-5倍,同时保留所需数据。
在启动大规模爬虫之前,请根据所选工具计算预期的流量,并将其纳入代理预算。如果任务需要JavaScript渲染和对抗反机器人系统的稳定性,请先在小规模页面集上进行测试,通过住宅代理——这将使您能够在启动全量数据之前准确评估实际的GB消耗。