最近在开发一个基于 Playwright 的自动化采集系统,目标站点部署了 Cloudflare 的防护策略。开发过程中遇到了一个非常典型的问题:代码在本地 Mac 上跑得畅通无阻,一旦部署到腾讯云的 Linux 服务器上,没过多久就会触发 403 Forbidden 或无限弹人机验证(CAPTCHA)。
已经配置了 playwright-stealth 插件,User-Agent、WebGL、Canvas 等浏览器指纹信息都做了对齐,为什么还是被拦截?本文记录完整的排查过程与解决思路。
1. 初步分析:请求头与指纹 首先确认了请求头(Headers)和浏览器环境指纹。navigator.webdriver 已隐藏,时区和语言设置也与目标站点匹配。按理说,WAF(Web 应用防火墙)不应该轻易识别出这是一个自动化脚本。
2. 深层排查:TLS 指纹(JA3/JA4) 进一步分析发现,Cloudflare 等现代化防护系统不仅检查浏览器层面的指纹,还会在传输层检查 TLS 握手的指纹(JA3/JA4 哈希)。 虽然 Playwright 启动的是真实的 Chromium,但如果在启动参数中没有做好处理,其底层网络栈的握手特征仍然可能与常规浏览器有细微差异。可以通过注入特定的启动参数来缓解:
# 优化 Playwright 启动参数
browser = p.chromium.launch(
headless=True,
args=[
'--disable-blink-features=AutomationControlled',
'--no-sandbox',
'--disable-setuid-sandbox'
]
)3. 根本原因:云服务器的出口 IP 被标记 在优化了 TLS 指纹后,成功率有所上升,但跑了几百次请求后,403 依然大面积爆发。 使用 curl -s https://ipinfo.io/json\ 检查服务器的公网 IP,发现其 ASN 归属于腾讯云(数据中心网段)。
原理解析:Cloudflare 等安全厂商维护着庞大的 IP 信誉库。云服务器(AWS、阿里云、腾讯云等)的 IP 段因为常被用于发起自动化攻击或高并发扫描,信誉分数极低。当 WAF 检测到请求来自这些高危机房 IP 段时,哪怕你的浏览器指纹伪装得再完美,也会直接触发最高级别的验证甚至封禁。
要让自动化脚本稳定运行,除了在应用层做好指纹伪装,在底层网络环境上,必须使用纯净的住宅 IP(Residential IP)。住宅 IP 的 ASN 归属于当地运营商,在 WAF 的信誉库中属于“正常家庭用户”,不会触发基于 IP 类的降级策略。
以下是在 Playwright 中集成稳定网络出口的代码示例:
# ============================================
# Playwright 挂载住宅 IP 网络出口示例
# 服务商:1024Proxy
# 官网:https://1024proxy.com/?kwd=hyj-txy
# ============================================
from playwright.sync_api import sync_playwright
def run_crawler():
with sync_playwright() as p:
# 从 1024Proxy 后台获取的住宅网络出口参数
proxy_host = "gateway.1024proxy.com"
proxy_port = "端口号"
proxy_user = "用户名"
proxy_pass = "密码"
browser = p.chromium.launch(
headless=True,
proxy={
"server": f"http://{proxy_host}:{proxy_port}",
"username": proxy_user,
"password": proxy_pass
},
args=['--disable-blink-features=AutomationControlled']
)
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
viewport={"width": 1920, "height": 1080}
)
page = context.new_page()
# 访问目标站点
page.goto("https://example.com")
print(page.title())
browser.close()
if __name__ == "__main__":
run_crawler()使用住宅 IP 出口后,即便在服务器上长时间运行,403 报错率也降至极低水平,抓取流程恢复稳定。
动态渲染爬虫遭遇 403,表面上是前端的指纹对抗问题,但很多时候根源在于底层的网络环境。在代码层面做好 TLS 与浏览器指纹的伪装,在网络层面配置一个纯净的住宅 IP 出口,两者结合,才能最大程度保证自动化任务的连续性与成功率。
本文仅做技术开发交流,请确保所有数据采集行为符合目标网站的使用条款及相关法律法规,切勿用于非法用途。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。