知识

如何测试住宅代理的速度、成功率与位置准确度

只看速度是个糟糕的基准。如何正确地测量住宅代理的成功率、延迟百分位与地理准确度,附可复制粘贴的 Python 测试。

Chris Collins

Chris Collins

2026年7月14日 · 3 分钟阅读

“它有多快?“是评价一个住宅代理时问错了的第一个问题。一个在 200ms 内响应、却有一半时间被封的代理毫无用处;一个稍慢、但每次都返回真实页面的代理,才正是你想要的。在你信任一个供应商、或排查你的抓取器为何表现不佳之前,你需要客观地测量三件事:成功率延迟分布,以及位置准确度。这份指南给你每一项的可复制粘贴测试,而同样重要的是,如何在不自欺的前提下读懂这些数字。

下面的一切都是对着 Shifter 的住宅 gateway运行的(一个端点 p.shifter.io:443,定位编码在用户名里),但这些测试是与供应商无关的,换掉主机和凭据,它们在任何地方都能用。示例是 Python;客户端配置与用 Python 使用住宅代理一致。

真正重要的三个指标

原始速度是人们最执着、却在孤立看待时最没用的指标。住宅 IP 经由真实的消费者设备路由,所以它们天生就比数据中心稍慢,这是意料之中的,不是缺陷。真正决定一个代理是否适合你工作的:

  • 成功率 —— 在你发送的请求中,有多少返回了真实页面(而非封锁、CAPTCHA 或错误)。这是决定你的数据管道是否完整的那个数字。
  • 延迟分布 —— 不是平均值,而是离散度。p95 和尾部告诉你,你那些慢请求会慢到多糟,而这正是在规模上让你痛的地方。
  • 位置准确度 —— 当你定位一个国家或城市时,出口 IP 是否真的解析到那里?对于任何地理定位用例,错误位置的数据就是悄无声息地错误的数据。

三者都要测。单一一个数字,尤其是平均速度,会藏起那些真正要紧的问题。

配置

把凭据放在环境变量里,并定义一个构建带定位代理 URL 的辅助函数:

import os, time, statistics, requests
USER = os.environ["SHIFTER_USER"]
PASS = os.environ["SHIFTER_PASS"]
GATEWAY = "p.shifter.io:443"
def proxy(country="us", city=None, sid=None, ttl=600):
parts = [USER, "country", country]
if city: parts += ["city", city]
if sid: parts += ["sid", sid, "ttl", str(ttl)]
url = f"http://{'-'.join(parts)}:{PASS}@{GATEWAY}"
return {"http": url, "https": url}

首先,做个健全性检查,确认你确实是在经由代理走,令人意外的是,相当多的”代理很慢”报告,其实是从未离开本地机器的流量:

r = requests.get("https://api.ipify.org?format=json", proxies=proxy("us"), timeout=30)
print(r.json()) # 应该是一个住宅 IP,而不是你自己的

测试 1:位置准确度

定位一个国家(可选再定位一个城市),向一个 geo-IP 端点询问出口 IP 在哪里,并在多次采样上测量匹配率。每个请求都轮换(不带 sid),这样你采样的是整个池,而不是一个 IP:

def test_geo(country="us", n=50):
hits = 0
for _ in range(n):
try:
r = requests.get("http://ip-api.com/json", proxies=proxy(country), timeout=30)
data = r.json()
if data.get("countryCode", "").lower() == country.lower():
hits += 1
except requests.RequestException:
pass
print(f"{country}: {hits}/{n} = {hits/n:.0%} country-accurate")
test_geo("us")
test_geo("de")

如何解读。 国家准确度应该很高(可以想成 90% 出头到接近 100%)。城市准确度天生更模糊,各个 geo-IP 数据库对一个 IP 属于哪座城市并不一致,所以一次”未命中”可能是数据库之间的分歧,而不是代理把你送到了错误的地方。有两个能救你于错误结论的注意点:如果可以,就用你目标站点所用的同一个 geo-IP 数据源来测城市准确度;并且永远不要把单一一个查询供应商当作绝对真相。

测试 2:延迟,以分布来测量

在多次采样上测量总请求时间,并报告百分位,而不是平均值。平均值会把恰好在规模上让你痛的那条慢尾巴给抹平:

def test_latency(country="us", n=50, url="https://api.ipify.org"):
times = []
for _ in range(n):
start = time.perf_counter()
try:
requests.get(url, proxies=proxy(country), timeout=30).raise_for_status()
times.append((time.perf_counter() - start) * 1000) # ms
except requests.RequestException:
pass
times.sort()
p = lambda q: times[min(len(times)-1, int(q*len(times)))]
print(f"n={len(times)} p50={p(0.5):.0f}ms p95={p(0.95):.0f}ms max={times[-1]:.0f}ms")
test_latency("us")

如何解读。 看 p50 对比 p95:离散度紧凑(p95 接近 p50)意味着性能可预测;p95 是 p50 的许多倍,则意味着一条会拖住并发 worker 的沉重尾巴。要把代理的开销与目标的慢分开,就对着一个快速、中性的端点(比如一个 IP echo)和你的真实目标各跑同一个测试,两者之差大致就是目标自身的延迟。并且不要把住宅的 p50 与数据中心的 p50 当成同一个产品来比;住宅按设计就多了一跳真实设备(见住宅代理 vs 数据中心代理)。

测试 3:成功率,最要紧的那个

对着你的真实目标跑请求(成功是与目标相关的),并对每个结果分类。这里的陷阱是相信 HTTP 状态码:一个 200 OK 仍可能是一次软封锁,一个以 200 投递的 CAPTCHA 或”请验证”页面。所以要校验内容,而不只是状态码:

def looks_like_real_page(html):
# 按你的目标调整:预期标记的存在、封锁标记的缺失。
block_markers = ("captcha", "are you a robot", "access denied", "unusual traffic")
low = html.lower()
return len(html) > 1000 and not any(m in low for m in block_markers)
def test_success(url, country="us", n=100):
ok, soft_block, errors = 0, 0, 0
for _ in range(n):
try:
r = requests.get(url, proxies=proxy(country), timeout=30)
if r.status_code == 200 and looks_like_real_page(r.text):
ok += 1
else:
soft_block += 1 # 200 但封锁、403/429/503 等
except requests.RequestException:
errors += 1 # 超时、连接失败
print(f"success={ok/n:.0%} blocked={soft_block/n:.0%} errors={errors/n:.0%}")
test_success("https://your-target.example/page", country="us")

如何解读。 成功率是抓取的头号指标,它是返回了可用数据的请求占比。把失败分成被封(目标拒绝了你)与错误(网络/超时),因为它们的修法不同:持续的封锁指向 IP 质量或请求行为(为什么爬虫会被封),而错误指向超时或过紧的地理过滤。注意,每个请求轮换加上一个重试循环,会抬高你的有效成功率,所以如果你在生产里就是这么跑的,就把裸的(单发)和带重试的都测一下。

把它们拼在一起

一个最小的测试框架跑完三项并打印一份报告:

if __name__ == "__main__":
for cc in ("us", "de", "gb"):
print(f"\n== {cc.upper()} ==")
test_geo(cc, n=50)
test_latency(cc, n=50)
test_success("https://your-target.example/page", country=cc, n=100)

按这个顺序读:先看成功率(数据到底回没回来?),再看延迟尾部(并发之下它跟得上吗?),再看地理准确度(是不是正确的数据?)。一个在 p50 上赢、却在成功率上输的供应商,对抓取而言是个错误的选择。

会产出误导性数字的常见坑

  • 报告平均延迟。 用百分位,是尾部在打垮并发任务。
  • 相信状态码 200。 软封锁会以 200 返回一个 CAPTCHA 页面。要校验内容。
  • 样本太小。 5 个请求什么都说明不了;用足够多(50 到 100+)才能看到分布和尾部。
  • 错误的地理绝对真相。 不同的 geo-IP 数据库并不一致,尤其在城市级。用你目标所用的数据源来测,并把城市准确度当作天生就比国家更模糊。
  • 拿住宅和数据中心比原始速度。 是不同的产品;住宅拿一点延迟换来了真实用户的信任,以及在受防护目标上更高的成功率(哪种代理更适合抓取)。
  • 没确认你在走代理。 在给任何东西做基准之前,先验证出口 IP 变了。

关于负责任地行事的一点说明

对着你被允许访问的端点做基准,速度和地理用公开的 IP echo 服务,成功率用你自己经授权的目标。把样本量保持在合理范围,别为了测一个站点而猛击它,并遵守速率限制。我们的可接受使用政策是 Shifter 上何为允许的权威依据。

常见问题

住宅代理多高的成功率算好? 这完全取决于目标,一个防守森严的站点会比一个开放的站点封得更多。要紧的是对着你的目标去测量它,并在同一个目标上比较各家供应商。把失败分成封锁与错误,好知道该修什么。

为什么我的住宅代理比数据中心的慢? 因为它经由一个真实的消费者设备路由,那一跳按设计就增加了延迟。这是为换取真实用户信任、以及在会封数据中心 IP 的站点上更高成功率所付的代价。用成功率和延迟分布来评判住宅,而不是拿裸的 p50 去比数据中心。

我该如何测试城市级的位置准确度? 定位那座城市,并把出口 IP 对着一个 geo-IP 数据源核对,最好是你目标所用的同一个。预期国家准确度会很高,而城市准确度更模糊,因为各个 geo-IP 数据库对城市边界并不一致。见何时城市级定位很重要

为什么一个 200 响应仍算作失败? 因为站点会投递软封锁,以 200 状态返回 CAPTCHA 或”验证你是人类”的页面。如果你只查状态码,就会把封锁记成成功。要校验内容是否与一个真实页面的样子相符。

我该用轮换会话还是粘性会话来测试? 两者都要,取决于你的工作负载。轮换(不带 sid)采样整个池,适合宽泛抓取;粘性(粘性 vs 轮换)测试多步流程。测量你在生产里真正会跑的那种模式。

底线

好好测试一个住宅代理,意味着拒绝把它简化成单一一个速度数字。用内容校验对着你的真实目标测量成功率,把延迟当作一个分布来测、并留意 p95 尾部,用一个明智的 geo-IP 绝对真相来测位置准确度,你就会知道一个供应商是否真的适合你的工作,而不是从一个营销数字去猜。是池的质量在推动这三者,所以理解 IP 信誉有助于你解读结果。

如果你在给各家供应商做基准、或在排查你自己的成功率,就对着住宅 gateway和你选定的目标跑这些测试。定价页面有按 GB 计费的套餐,可以拿它对着你在意的市场和站点试用。

准备好开始了吗?

试用 Shifter 住宅代理,205M+ 个 IP,195+ 个国家,低至 $0.75/GB。

立即开始