先说结论
选代理类型的决策依据只有一个:目标站点会不会识别并拦截你。价格、速度、IP 池规模都是次要的,因为一旦被拦,再便宜的通道也产生不了数据。
很多项目在这里走弯路:为了省钱全量用数据中心代理,结果成功率掉到 30%,反复重试反而消耗了更多资源和时间;或者反过来,对毫无防护的内部接口用住宅代理,把成本抬高了十倍。
两类代理的本质差异
数据中心代理的出口在机房,IP 段在公开的云服务商和 IDC 名录里,目标站点可以整段识别。住宅代理的出口是真实家庭宽带设备,IP 随机分散且会回收轮换,识别成本高得多。
| 维度 | 数据中心代理 | 住宅代理 |
|---|---|---|
| 出口位置 | 机房 | 真实家庭宽带 |
| 延迟 | 低,通常 10–50ms | 中,通常 100–800ms |
| 被识别概率 | 高,IP 段公开 | 低 |
| IP 池规模 | 大,但段位集中 | 极大,且分散 |
| 计费方式 | 按 IP 数或带宽 | 按流量 |
| 单位成本 | 低 | 高 |
怎么判断目标站点的防护强度
不要靠猜,用一次小批量测试就能得到答案。做法是:用数据中心代理固定 IP,对目标 URL 连续发 200 次请求,记录成功率。
- 成功率稳定在 95% 以上:防护很弱,直接用数据中心代理
- 成功率在 60%–95% 波动:有速率限制或初级 IP 信誉库,可以考虑降低并发或用住宅
- 成功率低于 60%:有明显风控,必须用住宅代理
- 大量返回验证码页而不是 4xx:有行为风控,需要配合住宅代理 + 浏览器指纹处理
关键是把”返回 403″和”返回验证码页但状态码 200″区分开。后者最容易被忽略——程序看到 200 就当作成功,实际抓回来的是空数据,最后表现为”数据莫名其妙变少了”。
# 判断一次响应到底是成功还是被风控拦截
BLOCK_MARKERS = ("验证码", "captcha", "access denied", "unusual traffic", "请稍后再试")
def classify(resp) -> str:
body = resp.text[:4000].lower()
if resp.status_code in (403, 429):
return "blocked"
if any(m.lower() in body for m in BLOCK_MARKERS):
return "challenged" # 状态码是 200,但内容不是你要的
if len(body) < 500:
return "suspiciously_small"
return "ok"
混合路由:让便宜的通道承担大部分流量
成熟的项目不会二选一。把请求按目标域名分流,防护弱的部分走数据中心,难啃的部分走住宅,成本会明显低于全量住宅。
# 按域名选择通道:内部接口和静态站走数据中心,电商前台走住宅
DC_PROXY = "http://dc-user:pass@dc.proxy.example:8080"
RES_PROXY = "http://res-user:pass@res.proxy.example:8080"
RESIDENTIAL_HOSTS = {
"shop.example.com",
"www.example-market.com",
"ads.example-network.com",
}
def proxy_for(url: str) -> str:
from urllib.parse import urlparse
host = urlparse(url).hostname or ""
for h in RESIDENTIAL_HOSTS:
if host == h or host.endswith("." + h):
return RES_PROXY
return DC_PROXY
这样做的收益在真实项目里通常是三到五倍的成本差异,而不是百分之几十。
住宅代理的流量成本压降顺序
住宅代理按流量计费,所以优化目标是”每个有效数据点消耗多少流量”。按下面的顺序做,收益是递减的:
- 拦截静态资源。图片、字体、视频、样式表通常占页面流量的 50%–80%,而且对结构化数据抓取毫无价值。
- 优先调用站点接口。能用 JSON 接口就不要渲染整个页面,一个接口响应可能只有几十 KB,而完整页面是几百 KB 到几 MB。
- 对防护弱的域名分流到数据中心。见上面的混合路由。
- 合理缓存。同一个页面在短时间内重复抓取是纯浪费。
第一步的收益最大,也最容易实现。在 Playwright 里只需要一个路由拦截:
from playwright.sync_api import sync_playwright
BLOCK = {"image", "font", "media", "stylesheet"}
with sync_playwright() as pw:
browser = pw.chromium.launch()
page = browser.new_page()
page.route("**/*", lambda route: (
route.abort() if route.request.resource_type in BLOCK else route.continue_()
))
page.goto("https://shop.example.com/item/123", timeout=60000)
html = page.content()
browser.close()
一个常见的误判
如果住宅代理的成功率也不理想,先不要急着换供应商。大多数情况下问题出在请求模式而不是代理质量:
- 同一个 IP 上并发过高
- 请求间隔过于规律(固定 sleep 0.5 秒这类)
- 缺少正常的 Referer 和 Accept-Language 头
- 会话标识没有正确轮换,导致上百个请求共用一个出口
这些都会让任何代理池的表现变差。排查方法见 爬虫 IP 被封的 7 个真实原因。
小结
先用小批量测试量出目标站点的防护强度和你的成功率基线,再决定通道配置。对多数项目来说,数据中心代理承担大部分流量、住宅代理只用于难啃的域名,是成本与成功率之间最优的组合。
取舍结论
| 维度 | 结论 |
|---|---|
| 前提条件 | 已用固定数据中心 IP 对目标 URL 做过 200 次请求的成功率基线测试。 |
| 核心取舍 | 住宅代理成功率高但按流量计费、单价高;数据中心代理便宜快速,但 IP 段公开、容易被整段识别。 |
| 不适用场景 | 需要长期登录态的任务不要用动态住宅——出口持续变化会反复触发二次验证。 |
一句话:用成功率数据定通道,让便宜的数据中心代理承担大部分流量,住宅只留给难啃的域名。
在你的目标站点上验证这套方案
文中的做法都可以用试用额度直接跑通。用你自己的目标站点测一轮,成功率数据比任何评测都可靠。