这是我们和客户聊得比任何话题都多的一段对话:“你们的住宅代理肯定被标记了,我在被封。“我们一查,IP 是干净的、高信誉的住宅地址。问题不在代理。在于请求是怎么发出去的。
一个住宅 IP 给你买到的是一样东西:一个干净的网络身份。它没给你买到一个干净的请求。反爬系统看的是几十个信号,IP 只是第一个。如果你流量的其它一切——请求头、时序、指纹、会话行为——都在说”自动化”,一个完美的住宅 IP 也救不了你。大多数住宅代理检测,是在配置这一层自己造成的,而不是 IP 的失败。
这是一份面向实践者的指南,讲那些照样让好住宅代理被检测到的错误,以及每一个怎么修。
1. 在会话中途轮换 IP
最常见的错误,也是最自毁的。你在一个 IP 上登录,然后下一个请求——去取登录之后那个页面的——却从另一个 IP 发出去。从站点的视角看,一个已认证的会话刚刚瞬移到了一个新地址。这是一个即时红旗,而且任何 IP 质量都修不了它。
修法:让你的轮换模式匹配任务。多步骤流程(登录、浏览、结账)需要一个 sticky 会话——一个 IP 在整个序列里保持不变。按请求轮换是给无状态、互相独立的抓取用的。把两者搞混——该钉住时却轮换——是”我的住宅代理被检测到了”的最大单一原因。(该用哪个、什么时候用,见 sticky vs 轮换。)
2. 把一个 IP 锤得太狠
相反的错误。你钉住一个 sticky IP,在一个很窄的时间窗里通过它打出几千个请求。一个真实的住宅用户不会一分钟加载 5000 个页面。哪怕是一个无瑕的 IP,当请求量是超人级别时,也显得自动化。
修法:把负载摊到池子上。只在流程真正需要一个身份的那段时间里用 sticky 会话,然后轮换。把每个 IP 的请求速率保持在人类范围内。一个大池子的意义就在于,没有任何单个 IP 扛着可疑的负载——把那点废掉,你就把池子也废掉了。
3. 与 IP 矛盾的地理信号
你经一个德国住宅 IP 路由,但你的请求发的是 Accept-Language: en-US,你浏览器的时区是 America/New_York,你的 locale 设置是美国的。IP 说德国;其它一切说美国。这个矛盾是教科书级的检测信号,而它完全在你的掌控之中。
修法:让每一个地理信号都和 IP 对得上。当你定位一个国家时,把 Accept-Language、时区、locale、以及任何货币/区域设置都对齐到匹配。一个在某地的住宅 IP,只有当请求的其余部分也属于那个地方时,才令人信服。
4. 一个尖叫着”自动化”的指纹
IP 是住宅的,但请求是由 python-requests/2.x 发出的,带着三个顺序错乱的请求头,以及一个不匹配任何真实浏览器的 TLS 握手。反爬系统读 User-Agent、请求头的集合与顺序、以及 TLS/JA3 指纹,而它们之间的不一致(一个”Chrome”的 User-Agent 配一个 Python 的 TLS 指纹)是一记明显的破绽。IP 是住宅的;客户端却明摆着是个脚本。
修法:发一个连贯的、与浏览器一致的指纹。用一个真实的 User-Agent、发出真实浏览器会发的整套请求头并保持正确顺序、并使用一个其 TLS 指纹与你声称的那个浏览器相符的客户端。代理指纹深入讲了这一层——它是”不被发现”里最被低估的那一半。
5. 泄露 DNS(socks5 vs socks5h)
一个微妙的。如果你用 socks5:// 而不是 socks5h://,你的机器会在请求经代理之前、在本地解析目标主机名。那次 DNS 查询从你的真实网络发出,这可能泄露你真实的位置,而且在某些配置下,会因为 DNS 解析和连接来自不同地方而暴露出有代理在用。
修法:在代理侧解析 DNS。用 socks5h://(那个 h),或者对 HTTP 代理,确保客户端没有在预解析。这让整个请求——包括查询——都从住宅出口发起。(更多见 SOCKS5 用于自动化。)
6. 不像人的请求模式
哪怕 IP 和指纹都完美,行为也会出卖你。请求以精确、机器般规律的间隔打出。动作之间零思考时间。十个”用户”从一个会话里以完美并行打同一个端点。没有 cookie、不加载资源、不跑 JavaScript,只有人类浏览器孤立地永远不会产生的、裸的 HTML 抓取。
修法:表现得像个人。加入随机化的延迟、让你的时序有变化、别以完美均匀的间隔打请求、也别在一个身份下跑不可能的并发。在 IP 和指纹检查通过之后,行为检测越来越是抓住爬虫的那一关。
7. 把一个身份带过许多 IP
错误 #1 的镜像。你在一个 IP 上拿到一个会话 cookie,然后为了摊负载,把同一个 cookie 跨几十个不同的 IP 复用。从站点的视角看,一个已登录的账号同时从二十个不同城市的地址连进来。没有真实用户会这么干。
修法:让身份和 IP 绑在一起。一个会话、一个 sticky IP,持续那个会话的生命周期。如果你轮换 IP,就开一个全新的会话——别把旧身份的 cookie、local storage 或 token 拖到一个新地址上。
8. 无视软封禁、盲目重试
你撞上一个 CAPTCHA 或一个 429,而你的爬虫就在同一个 IP、以同样的速率立刻重试同一个请求。每一次重试都在向站点确认你是自动化的,并把红旗升级——常常从”显示一个 CAPTCHA”升到”封掉这个 IP”。
修法:把软封禁当作信号,而不是噪声。退避、轮换 IP、放慢、并重新考虑触发那次挑战的模式。盲目重试会把一个可恢复的软封禁变成一个硬封禁。(通用处理见如何避免被封。)
9. 把地理约束收得太紧,直到池子坍塌
你定位 国家 + 州 + 城市 + ASN,因为越精确越好,对吧?现在匹配的池子小得可怜,于是网关一遍又一遍把同样那几个 IP 递给你。你把一个庞大、多样的住宅池变成了五个地址的轮换,每一个都扛着你全部的负载——这会很快把它们烧掉。
修法:只收到任务需要的那么紧。如果站点在意的是国家,就定位国家,而不是城市 + ASN。过度约束会缩小池子的多样性、集中你的足迹——这正是住宅代理用途的反面。(只有当目标真的需要时,才经 IP 轮换去用窄地理。)
10. 浏览器自动化的泄露
当你驱动一个真实浏览器(Puppeteer、Playwright、Selenium)经住宅代理时,浏览器本身可能出卖你。WebRTC 可能暴露你在代理背后的真实 IP。无头模式的破绽、缺失或自动化专属的属性、以及默认的自动化标志,都在信号一个机器人——无论出口 IP 多干净。
修法:加固浏览器。禁用或路由 WebRTC,让它泄露不了真实 IP;去掉无头破绽;并把自动化框架配置成表现得像一个正常浏览器。一个住宅 IP 摆在一个明摆着是自动化的浏览器前面,是一个被浪费的住宅 IP。
所有这些背后的那个共同模式
上面每一个错误都有同一个根:把住宅 IP 当作整套伪装,而不是它的一层。检测是整体性的。反爬系统从 IP、指纹、地理信号、会话行为和时序里拼出一幅画,然后标记其中的矛盾。一个带着 Python 指纹、美国请求头、机器时序、和一个共享 cookie 的住宅 IP,不是一个住宅用户——它是一个套着住宅 IP 的脚本,而现代检测一眼看穿。
把 IP 搞对(干净、住宅、管理良好),然后让其它每一个信号都和它对上。这就是全部的手艺。
常见问题
如果 IP 是干净的,我的住宅代理为什么还被检测到? 因为 IP 只是一个信号。如果你的指纹(User-Agent、请求头、TLS)、地理设置、会话行为或请求时序与住宅 IP 矛盾,反爬系统就会标记这个矛盾。大多数住宅代理检测是配置问题,不是 IP 问题。
最常见的住宅代理错误是什么? 在会话中途轮换 IP——在一个登录和它之后的请求之间换地址,于是一个已认证的会话看起来在 IP 之间跳。任何多步骤流程都用一个 sticky 会话。
住宅代理会隐藏我的指纹吗? 不会。住宅代理改变的是你的 IP,别的不变。你的 User-Agent、请求头顺序、TLS/JA3 指纹、浏览器属性都没变,必须单独把它们做成一致的。IP 和指纹是相互独立的两层。
地理不匹配会让一个住宅代理被封吗?
会。一个在某国的 IP,配着另一国的 Accept-Language、时区和 locale,是一个经典的检测信号。把每一个地理信号都和 IP 的位置对齐。
为什么过度定位地理有害? 约束到 国家 + 州 + 城市 + ASN 会缩小匹配的池子,于是你复用同样那几个 IP、集中你的足迹,很快把那些 IP 烧掉。只定位到任务需要的那么精确。
CAPTCHA 之后我该立刻重试吗? 不该。在同一个 IP 上立刻重试会确认自动化,并把软封禁升级成硬封禁。退避、轮换、放慢,并重新想想触发那次挑战的模式。
结论
一个住宅 IP 是看起来像人的必要条件,但远远不够。最让实践者抓狂的那些检测——“我有好代理却还是被封”——几乎总是自己造成的:一个轮换错误、一个指纹不匹配、一个地理矛盾、或不像人的时序。修好那些,你那些干净的 IP 才终于能干它们该干的活。
如果你怀疑 IP 就是问题,那也值得排查,IP 信誉讲了怎么评估一个池子。但远更常见的是,修法在你这一侧的连接上。从一个优质的住宅网络起步,让 IP 这一层是稳的,然后让请求里其它每一个信号都和它对上。代理只能带上你给它的那套伪装。