“是否应该每次请求都轮换?”是团队开始使用住宅代理时最先问的问题之一,诚实的答案是:这取决于你的请求之间有什么共同点。轮换过于频繁会破坏那些网站预期来自同一访问者的流程。轮换过少又会把所有流量堆积到一个地址上。这两种情况都会导致封禁、重试和带宽浪费。
本指南提供一个简单的判断方法。关键问题根本不在于代理本身,而在于你的工作:哪些请求属于同一组,以及持续多长时间。
三种模式
| 模式 | 作用 | 在 Shifter 上 |
|---|---|---|
| 按请求轮换 | 每个请求都从不同的住宅 IP 发出 | 默认模式:用户名中没有会话标志 |
| 粘性会话 | 具有相同会话 ID 的请求共享一个 IP,直到会话结束 | 在用户名中添加 sid-<id>,可选添加 ttl-<seconds>;默认生命周期为 120 秒 |
| 固定 IP | 在整个计费周期内使用某个城市和 ISP 的一个地址 | ISP 代理 |
如果粘性会话背后的住宅 IP 断线,该会话也会提前结束,因此使用会话的代码应预期在会话中途偶尔会出现新的 IP。粘性会话按区域保留,因此共享同一会话的工具应通过同一个区域入口点连接。
关键问题:哪些请求属于同一组?
查看你的爬虫重复执行的最小工作单元,并针对它问两个问题。
1. 一个单元由多少个请求组成? 单独抓取的一个产品页面是一个请求。一次搜索加上六个详情页是一个流程。一次结账测试是一个带有状态的流程:购物车、会话 cookie,或许还有 CSRF 令牌。
2. 一个单元需要多长时间? 几秒钟、几分钟,还是几小时?
根据这两个答案:
- 独立的单个请求:轮换。 每个页面都是独立的,保留一个 IP 没有任何好处,而将请求分散到多个地址上可以防止其中任何一个看起来太忙碌。
- 30 分钟内完成的流程:粘性会话。 网站在第一个请求时设置 cookie,并期望流程的其余部分来自同一访问者。在搜索或购物车进行到一半时更换 IP 看起来像会话被劫持,这是导致突然封禁和状态丢失的常见原因。
- 任何更长的流程,或者你会反复登录的账户:固定 IP。 粘性会话是为几分钟设计的,不是几小时。对于持续一整天的会话,或者每天都要用的账户,使用 ISP 代理。我们关于长会话 ISP 代理设置的指南详细介绍了这一点。
用代码表示
下面两个函数编码了这个规则,并构建匹配的 Shifter 用户名:
def proxy_username(user, country=None, session_id=None, ttl_seconds=None):
"""Build a Shifter residential username: rotate per request, or stick to one IP."""
parts = [f"customer-{user}"]
if country:
parts.append(f"country-{country}")
if session_id:
parts.append(f"sid-{session_id}")
if ttl_seconds:
parts.append(f"ttl-{ttl_seconds}")
elif ttl_seconds:
raise ValueError("ttl only works together with a session id")
return "-".join(parts)
def choose_rotation(steps, minutes, needs_login=False, same_ip_required=False):
"""Pick a rotation mode for one unit of work.
steps: requests that belong together (one page = 1, a checkout flow = many)
minutes: how long that unit of work takes
"""
if needs_login and minutes > 30:
return "isp" # a login that outlives a sticky session
if steps == 1 and not same_ip_required:
return "rotate" # independent requests: new IP each time
if minutes <= 30:
return "sticky" # a short flow: one IP until it ends
return "isp"
应用于四个典型任务:
from rotation import choose_rotation, proxy_username
jobs = { # session ids must not contain hyphens: the username uses them as separators
"products": dict(steps=1, minutes=0.1),
"search": dict(steps=6, minutes=2),
"checkout": dict(steps=15, minutes=8),
"seller": dict(steps=400, minutes=240, needs_login=True),
}
for name, job in jobs.items():
mode = choose_rotation(**job)
if mode == "rotate":
user = proxy_username("USERNAME", "us")
elif mode == "sticky":
user = proxy_username("USERNAME", "us", session_id=name, ttl_seconds=job["minutes"] * 60 + 120)
else:
user = "an ISP proxy username from your plan"
print(f"{name:<9} {mode:<7} {user}")
products rotate customer-USERNAME-country-us
search sticky customer-USERNAME-country-us-sid-search-ttl-240
checkout sticky customer-USERNAME-country-us-sid-checkout-ttl-600
seller isp an ISP proxy username from your plan
TTL 设置为流程预期时长加上两分钟的缓冲时间,这样会话的存活时间会略长于工作本身,但不会无限期延续。给每个并发流程都分配自己的会话 ID:两个工作进程共享一个 ID 就等于共享一个 IP,这就违背了初衷。
这个选择如何影响成本和成功率
成功率。 最常见的轮换错误是在一个流程内部轮换。第一个请求获得了一个 cookie,第二个请求却带着这个 cookie 从另一个国家的 ISP 发出,网站就会将其视为可疑行为。为流程使用粘性会话通常比其他任何单一改动都更能修复失败问题。相反的错误是,把成千上万个独立请求通过一个粘性 IP 发送,这会让那一个地址看起来像机器人。我们关于粘性与轮换住宅代理对比的指南深入探讨了这两种失败模式。
带宽。 住宅流量按 GB 计费,轮换本身不会改变这一点。真正改变它的是重试:每个失败的流程都要重新下载一次。让模式匹配工作性质可以减少重试,这才是节省的来源。在一个粘性会话内,复用同一连接和 cookie 还能避免重复下载相同的资源。
速度。 按请求轮换意味着每个请求都走一条新路线。如果你每次还都打开新连接,建立连接的时间就会累积起来。复用连接比轮换模式更重要;我们在你的爬虫很慢,问题很可能不在代理中的测试衡量了具体影响程度。
选错模式时的信号
| 你看到的现象 | 可能的原因 | 应做的改变 |
|---|---|---|
| 流程在第一步之后失败;购物车或会话丢失 | 在流程内部轮换 | 每个流程使用粘性会话 |
| 一个 IP 在一阵请求爆发后被封 | 一个粘性会话上承载了过多独立工作 | 对独立页面按请求轮换 |
| 会话在工作完成前就断开 | TTL 设置过短,或流程对粘性会话来说太长 | 提高 TTL;把耗时数小时的工作迁移到 ISP 代理 |
| 两个工作进程互相干扰 | 共享了同一个会话 ID | 每个并发流程使用各自的会话 ID |
| 登录每天都被要求验证 | 登录使用了轮换或粘性 IP | 每个账户使用固定的 ISP IP |
常见问题
我应该在每次请求时都轮换代理 IP 吗?
对于独立请求,比如抓取互不相关的产品页面,是的。对于跨越多个请求且带有共享状态的任何流程,比如搜索、购物车或登录,应在整个流程中使用粘性会话保持同一个 IP。
粘性会话应该持续多长时间?
应与它所服务的流程时长相当,再加上一点余量。在 Shifter 上默认为 120 秒,你可以用 ttl-<seconds> 来设置。超过大约 30 分钟的流程,以及你会反复登录的账户,应该使用 ISP 代理。
轮换 IP 能减少封禁吗?
它能分散负载,使任何单一地址都不会显得过于繁忙,这对独立请求有帮助。但在一个流程内部轮换则恰恰相反:它会让一个访问者看起来像多个访问者,这往往会被网站封禁。
轮换会影响带宽成本吗?
不会直接影响,因为住宅流量是按流量计费的。间接地,使用错误的模式会导致流程失败和重试,这些失败的内容会被重新下载,从而增加账单。
结论
对独立工作按请求轮换,对每个相互关联的流程保持一个粘性会话,对持续数小时或涉及反复登录的账户使用固定的 ISP IP。根据你的工作单元来判断,而不是根据代理设置,给每个并发流程分配各自的会话 ID,并留意上表中列出的信号。我们关于住宅代理轮换的工作原理的说明文章介绍了每种模式背后的机制。