我平时用网页抓取 API,最关心的并不是"单次能不能拿到内容",而是任务放大以后还能不能稳定返回:并发提高会不会明显变慢,成功响应里有没有空页面,偶发慢请求到底能拖到多久。
这次我用 Dataify 的通用采集 API 做了一轮实测。测试不跑竞品对比,只看它在静态页面、JavaScript 动态页面和慢响应页面三种场景下的真实表现。正式统计共 900 次请求,全程不重试,最终成功 884 次,总成功率和有效数据率均为 98.22%。
先把总结果放在前面:平均延迟 4.04 秒,P50 为 3.79 秒,P90 为 5.82 秒,P99 为 16.66 秒,最长一次 31.17 秒。下面展开说测试过程。
一、Dataify 通用采集 API
Dataify 控制台把搜索引擎采集、行业网站采集和通用采集 API 分开提供。本次只测试"通用采集 API",也就是传入目标 URL,由接口返回 HTML。控制台还提供 JavaScript 渲染、资源拦截、等待时间、国家/地区等参数,正好可以覆盖普通静态页和需要渲染的页面。

我开始测试时账户中有 50 积分。控制台当时显示通用采集 API 的价格为 15 元/千次请求,并注明只对成功请求计费。产品价格可能调整,实际使用时还是以控制台页面为准。

二、测试环境和规则
本次测试时间为 2026 年 8 月 16 日,运行环境如下:
| 项目 | 配置 |
|---|---|
| 操作系统 | Windows 11 家庭中文版,Build 26200 |
| Python | 3.12.13 |
| HTTP 客户端 | requests + 线程池 |
| Dataify 接口 | https://webunlocker.dataify.com/request |
| 返回类型 | HTML |
| 单次超时 | 60 秒 |
| 并发档位 | 1、5、10 |
| 每个场景、每档请求数 | 100 次 |
| 正式请求总量 | 3 × 3 × 100 = 900 次 |
| 重试 | 关闭 |
接口不支持从中国大陆出口直接发起请求,所以本次测试机通过本地 SOCKS5 代理使用境外网络出口。文章中的延迟包含"测试机---境外出口---Dataify---目标网页"整条链路,不等同于 Dataify 服务端内部耗时。
目标网页没有选择业务站点,而是使用三个公开、适合测试的页面:
| 场景 | 目标 | 渲染设置 | 有效性判断 |
|---|---|---|---|
| 静态页面 | https://example.com/ |
关闭 JS 渲染 | 正文达到最小长度且包含 Example Domain |
| 动态页面 | https://quotes.toscrape.com/js/ |
开启 JS 渲染 | 正文包含预期关键词,且存在 .quote 元素 |
| 慢响应页面 | https://httpbingo.org/delay/2 |
关闭 JS 渲染 | 正文达到最小长度且包含 headers |
每个目标在正式测试前预热 2 次,预热结果不计入 900 次统计。为了看清原始稳定性,程序没有自动重试;生产环境通常还会增加有限重试、退避和熔断策略。
三、我怎样判断"成功"和"有效"
抓取接口返回 HTTP 200,不代表页面内容一定可用,所以我把两个指标分开统计:
- 抓取成功率:Dataify 接口 HTTP 状态正常,并且返回的业务状态码处于成功范围。
- 有效数据率:在全部请求中,成功取得的 HTML 同时通过正文长度、关键词或 CSS 选择器校验的比例。
两个指标的分母都是该组的全部请求。比如 100 次请求中有 98 次接口成功,其中 97 份内容通过校验,那么成功率为 98%,有效数据率为 97%。
核心请求代码并不复杂,Token 从系统环境中读取,原始记录里也不保存完整 Token:
python
import os
import time
import requests
endpoint = "https://webunlocker.dataify.com/request"
token = os.environ["DATAIFY_API_TOKEN"]
def fetch(url, js_render=False):
payload = {
"url": url,
"type": "html",
"js_render": "True" if js_render else "False",
"country": "us",
"follow_redirect": "True",
"isjson": "1",
}
started = time.perf_counter()
response = requests.post(
endpoint,
headers={"Authorization": f"Bearer {token}"},
json=payload,
timeout=60,
)
latency_ms = (time.perf_counter() - started) * 1000
return response, latency_ms
内容校验采用 BeautifulSoup。不同页面使用不同的关键词和选择器,避免把空壳 HTML 或错误页算成有效数据:
python
from bs4 import BeautifulSoup
def validate_html(html, min_chars, keywords=(), selector=None):
if not html:
return False
soup = BeautifulSoup(html, "html.parser")
text = " ".join(soup.stripped_strings)
if len(text) < min_chars:
return False
if any(word not in text and word not in html for word in keywords):
return False
if selector and soup.select_one(selector) is None:
return False
return True
每次请求都会单独写入 CSV,字段包括场景、并发数、接口状态、业务状态、耗时、内容字节数、校验结果和错误类型。下面是脱敏后的实际运行记录:

四、900 次请求的实测结果
| 场景 | 并发 | 请求数 | 成功率 | 有效率 | 平均延迟 | P50 | P90 | P99 | 最长响应 |
|---|---|---|---|---|---|---|---|---|---|
| 静态页面 | 1 | 100 | 91% | 91% | 2.71s | 1.93s | 3.42s | 12.14s | 12.69s |
| 静态页面 | 5 | 100 | 100% | 100% | 2.21s | 1.87s | 2.88s | 7.57s | 8.56s |
| 静态页面 | 10 | 100 | 97% | 97% | 2.17s | 1.84s | 2.56s | 11.71s | 12.04s |
| 动态页面 | 1 | 100 | 100% | 100% | 4.97s | 3.91s | 7.11s | 16.85s | 23.22s |
| 动态页面 | 5 | 100 | 100% | 100% | 5.11s | 4.38s | 7.73s | 14.20s | 25.49s |
| 动态页面 | 10 | 100 | 100% | 100% | 6.75s | 5.02s | 10.42s | 30.44s | 31.17s |
| 慢响应页面 | 1 | 100 | 99% | 99% | 4.12s | 3.98s | 4.56s | 6.65s | 6.85s |
| 慢响应页面 | 5 | 100 | 98% | 98% | 4.12s | 3.85s | 4.55s | 11.64s | 11.73s |
| 慢响应页面 | 10 | 100 | 99% | 99% | 4.21s | 3.85s | 4.45s | 11.62s | 20.94s |

正式测试耗时约 26 分 05 秒。从成功率看,动态页面三档并发全部成功;慢响应页面稳定在 98%~99%;静态页面波动更明显,其中并发 1 的一组出现了 9 次失败。

这组数据里,成功率和有效数据率完全相同。原因不是把两者混成了一个指标,而是 884 次成功响应返回的 HTML 全部通过了对应内容校验;没有出现"接口成功但正文为空、缺关键词或缺选择器"的情况。
五、平均延迟之外,更应该看 P90 和 P99
平均值容易被少量慢请求拉高,分位数更适合观察批量任务的体验:P50 可以理解为典型请求,P90 表示 90% 的请求不超过该耗时,P99 则反映尾部慢请求。

静态页面的 P50 一直在 1.84~1.93 秒之间,典型请求比较稳定;动态页面由于需要 JavaScript 渲染,整体比静态页面慢。并发从 1 提高到 10 后,动态页面平均延迟由 4.97 秒升到 6.75 秒,P90 由 7.11 秒升到 10.42 秒,P99 达到 30.44 秒,说明并发上来以后尾部延迟明显放大。
慢响应页面本身固定等待约 2 秒。它在三档并发下的 P50 都接近 4 秒,但并发 10 时最长响应达到 20.94 秒,同样能看到少量长尾。
需要注意的是,每组只有 100 个样本,P99 基本对应最慢的少数请求,对偶发网络抖动非常敏感。它适合用来发现问题,但不能只凭单轮 P99 给服务下绝对结论。
六、16 次失败发生了什么
900 次正式请求中共有 16 次失败,分布如下:
| 场景 | 并发 1 | 并发 5 | 并发 10 | 合计 |
|---|---|---|---|---|
| 静态页面 | 9 | 0 | 3 | 12 |
| 动态页面 | 0 | 0 | 0 | 0 |
| 慢响应页面 | 1 | 2 | 1 | 4 |
这些失败的共同特征是:接口 HTTP 层返回 200,但响应中的业务码为 2001。测试程序将它们记为 http_error:api=200,target=2001。本轮没有出现客户端 60 秒超时,也没有出现成功响应内容校验失败。
由于现有结果只能确认业务码,不能可靠判断服务端内部原因,所以这里不做推测。从工程角度看,调用方至少应记录 HTTP 状态、业务码和请求耗时,并对可重试错误设置次数上限和退避间隔。
另一个值得注意的现象是,失败数没有随着并发数线性增加:静态页面并发 1 的失败反而多于并发 5。这说明单轮小样本会受时间段和网络波动影响,不能简单得出"并发越低成功率越高"或"并发 5 最稳定"的结论。
七、积分消耗
测试前余额为 50,完成接口摸底、脚本调试、预热和 900 次正式请求后,余额为 36.52,合计减少 13.48。

这个消耗包含前期调试请求,不能直接拿 13.48 除以 900 当作正式测试的单次成本。对我这次测试来说,50 积分足够完成验证,也留出了补测空间。
八、我的结论
从这 900 次请求看,Dataify 通用采集 API 的接入过程比较直接,静态 HTML 和 JavaScript 渲染页面都能用同一套接口处理。整体成功率 98.22%,成功返回的 884 份内容全部通过有效性校验,动态页面 300 次请求则全部成功。
它的主要观察点在长尾延迟。静态页面的典型响应约 2 秒,动态渲染页面在并发 10 时 P99 超过 30 秒。如果业务对完成时间敏感,不能只按照平均延迟设置超时;更合适的做法是结合 P90/P99 预留空间,同时加入有限重试、失败记录和并发控制。
这轮测试适合说明 Dataify 在当前网络、三个公开样本和并发 1~10 下的表现,不代表所有网站、地区和时间段。正式上线前,最好换成自己的真实目标页面再跑一轮小规模验证。
本文只采集公开、合法的测试页面。实际使用网页采集工具时,请遵守目标网站的 robots 规则、服务条款以及适用的法律法规,不采集非公开数据和个人敏感信息。
本次测试数据: 900 条原始 CSV 记录,测试时间 2026 年 8 月 16 日。
相关链接: Dataify 官网|Dataify 控制台
本文结论仅代表本次测试环境和测试样本,产品功能与价格以官方页面最新信息为准。