爬虫跑不动,八成不是代码问题,而是出口 IP 被识别了。目标站看到的是一个机房网段、同一个 ASN、每分钟几百次请求, 风控系统不用多聪明就能把它拦下来。爬虫代理要解决的,就是让每个请求从不同的真实家庭网络出去,把「这台机器在批量抓」 变成「很多个普通用户分别在访问」。
先分级,再选池子
不是所有站都值得为住宅 IP 付钱。先给目标分个级,钱花在会被拦的那一类上:
| 目标类型 | 例子 | 会检查什么 | 该用什么 |
|---|---|---|---|
| 开放型 | sitemap、公开 API、静态文档 | 只看频率 | 直连或机房 |
| 轻度防护 | 新闻站、博客、小电商 | User-Agent、粗粒度限频 | 机房,429 时轮换 |
| 识别 ASN | 搜索引擎、电商平台、航旅 | ASN、IP 信誉、请求频率 | 住宅,按请求轮换 |
| 识别指纹 | 社媒、票务、大型零售 | ASN + TLS/HTTP2 指纹 + 行为 | 住宅 + 匹配的浏览器环境 |
实际项目里,一次采集往往同时碰到三类:受保护的 HTML 页面、开放的 JSON 接口、放图片的 CDN。按域名分流,只让第一类走住宅, 住宅流量通常能省下三分之一。
轮换、并发、节奏:三个你能控制的东西
IP 信誉你控制不了,但你能控制「每个 IP 打多少次」和「请求长什么样」。前者靠轮换,后者靠请求头、Cookie 和间隔。
# requests:每个请求换一个 IP,最简单也最有效
import requests, uuid
def proxy():
user = "账号-country-us-sid-" + uuid.uuid4().hex[:12]
p = "http://%s:密码@网关:端口" % user
return {"http": p, "https": p}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
}
r = requests.get("https://目标站/商品页", proxies=proxy(), headers=headers, timeout=30)
print(r.status_code, len(r.text))
# Scrapy:中间件里换 IP + 自动限速,别把并发写死 # settings.py CONCURRENT_REQUESTS = 16 CONCURRENT_REQUESTS_PER_DOMAIN = 8 DOWNLOAD_DELAY = 1.0 RANDOMIZE_DOWNLOAD_DELAY = True AUTOTHROTTLE_ENABLED = True AUTOTHROTTLE_TARGET_CONCURRENCY = 4.0 RETRY_TIMES = 2 DOWNLOADER_MIDDLEWARES = { "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None, "myproject.middlewares.RotatingProxy": 543, }
重试要换新的 sid,不要拿同一个会话反复撞。403 通常说明「这条 IP 被打爆了」,不是「这个 URL 打不开」,
换 IP 重试一次,成功率能回来一大半。
别渲染你能直接读的东西
开一个无头浏览器,流量是普通 HTTP 请求的 10~50 倍,而你买的正是流量。动手写 Playwright 之前先确认三件事:
页面有没有 JSON-LD 或 __NEXT_DATA__、有没有可以直接调的 JSON 接口、不执行 JS 的 HTML 里是否已经有你要的字段。
实际项目里,大约三分之二的商品页和列表页能用上面任意一条解决。
成本怎么算
| 项目 | 数值 | 算法 |
|---|---|---|
| 页面大小 | 400 KB | 只算 HTML,不加载图片 |
| 1GB 能抓多少页 | 2,500 页 | 1,000,000 KB / 400 KB |
| 成功率 95% 时的请求数 | 1,053,000 次 | 1,000,000 / 0.95 |
| 总流量 | 约 421 GB | 1,053,000 × 400 KB |
| 费用($1/GB) | 约 $421 | 流量 × 单价 |
两个结论:第一,失败重试也在烧流量,所以成功率比单价更能决定成本;第二,最省钱的优化通常是「减少每页字节数」, 而不是「找更便宜的代理」。
被拦了,按这个顺序排查
| 现象 | 最可能的原因 | 怎么处理 |
|---|---|---|
| 换 IP 后仍是 403 | 指纹或账号态被封,不是 IP 问题 | 检查请求头、TLS 指纹、Cookie、访问间隔 |
| 返回 200 但内容是空壳 | 数据由 JS 渲染,或返回了验证页 | 找 JSON 接口;必要时才上无头浏览器 |
| 429 频繁 | 单域名并发过高 | 并发减半、延时加倍,别靠加 IP 解决 |
| 大量超时 | 命中了一条不健康的出口 | 换 sid 重试;每次请求都设 20~30 秒超时 |
| 时好时坏 | 地域/时段差异或 A/B 分流 | 固定国家与城市,记录时间戳再比对 |
| 流量消耗异常高 | 渲染或下载了图片/视频 | 拦掉静态资源,只取 HTML 与接口 |
合规提醒
代理改变的是请求来源,不改变行为的合法性。只采集你有权访问的公开数据,遵守目标站的 robots 规则与服务条款, 把请求频率控制在真人可能产生的范围内,不要用于撞库、刷单、绕过付费墙或规避平台已经对你作出的处罚。 数据用途的合规责任在使用方。
常见问题
爬虫一定要用代理 IP 吗?
不一定。公开 API、sitemap、静态文档这类目标不看你从哪里来,直连或者用机房 IP 就够。但电商、搜索引擎、社媒、航旅、房产这类站点会看 ASN、IP 信誉和请求频率,用服务器 IP 直接抓,通常几十个请求后就开始返回验证码或空页面。
爬虫代理和普通代理有什么区别?
区别在池子和轮换能力。爬虫要的是「每个请求换一个干净 IP」和「按目标国家/城市定位」,所以需要大池子 + 按请求轮换 + 会话控制。普通 HTTP 代理通常是少量固定出口,多个用户共用,在风控库里早就被标记了。
住宅代理和机房代理,爬虫该选哪个?
看目标站有没有反爬。没有反爬的站,机房代理更快更便宜;有反爬的站(亚马逊、Google、TikTok 等),机房 IP 的 ASN 一眼就被识别,必须用住宅。我们两种都卖,机房按流量 $1/GB、100GB 起,不是按 IP 卖。
采集 100 万页大概要多少流量、多少钱?
按一页 400KB、成功率 95% 算:需要约 1,053,000 次请求,流量约 421GB,住宅按 $1/GB 计算约 $421。如果每页都开无头浏览器渲染,流量会涨到 10~50 倍,成本跟着涨,所以能用接口或 JSON 就别渲染。
并发开多少合适?
按域名控制,不要按总量控制。起步 5~10 并发/域名,观察 429 和 403 的比例,稳定后再阶梯上调。同一个站把并发从 8 拉到 32,通常不会让吞吐涨 4 倍,只会让成功率掉一半。
被目标站封了怎么办?
先分清是「IP 被封」还是「指纹被封」。换个 sid 还是 403,说明不是 IP 问题,要看请求头、TLS 指纹、Cookie 和访问节奏。只看 IP 会导致不停加代理、成本翻倍但成功率不变。
按流量计费,流量会清零吗?
不清零,用多少算多少,没有月费门槛。上传和下载都计入流量,1GB 按 1000MB 计算,控制台可以按天看用量明细。