无头浏览器能渲染 JavaScript,能处理纯 HTTP 客户端搞不定的现代站点。但浏览器照样是从同一个 IP 发出所有请求,一旦站点限速或指纹化该地址,自动化就被抓。给 Playwright 和 Puppeteer 挂代理能把流量分散到多个 IP,做对了还能让自动化看起来像普通用户。下面是两者的可运行配置,Python 和 Node 都有。
在浏览器启动时设置代理。认证用独立的 username、password 字段传 —— 不要把凭据拼进 server URL:
from playwright.sync_api import sync_playwright
PROXY = {
"server": "http://gate.jibaoproxy.com:10001",
"username": "USERNAME",
"password": "PASSWORD",
}
with sync_playwright() as p:
browser = p.chromium.launch(proxy=PROXY, headless=True)
page = browser.new_page()
page.goto("https://httpbin.org/ip")
print(page.inner_text("body"))
browser.close()
极豹网关同时提供 HTTP 和 SOCKS5。浏览器自动化用 HTTP 入口:Playwright 和 Puppeteer 不支持带认证的 SOCKS5 代理,所以 HTTP+认证是可靠选择。
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
headless: true,
proxy: {
server: 'http://gate.jibaoproxy.com:10001',
username: 'USERNAME',
password: 'PASSWORD',
},
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
console.log(await page.innerText('body'));
await browser.close();
})();
Playwright 里最干净的轮换方式是每个 BrowserContext 一个 IP。每个 context 是独立会话(独立的 cookie 和缓存),把每个 context 绑定不同出口 IP,就能在一个浏览器进程里跑多个并行身份:
from playwright.sync_api import sync_playwright
def ctx_proxy(session_id):
return {
"server": "http://gate.jibaoproxy.com:10001",
"username": f"USERNAME-session-{session_id}",
"password": "PASSWORD",
}
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
for i in range(3):
context = browser.new_context(proxy=ctx_proxy(f"ctx{i}"))
page = context.new_page()
page.goto("https://httpbin.org/ip")
print(i, page.inner_text("body"))
context.close()
browser.close()
每个 context 用不同的 sticky 会话 token,所以 IP 在 context 内保持稳定(适合登录流),跨 context 又不同(适合多账号并行)。这正是 GoLogin、Dolphin Anty 等反检测浏览器自动化的模式 —— 参见我们的反检测浏览器代理设置指南。
Puppeteer 把代理服务器作为 Chromium 启动参数,然后在 page 对象上认证:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--proxy-server=http://gate.jibaoproxy.com:10001'],
});
const page = await browser.newPage();
await page.authenticate({ username: 'USERNAME', password: 'PASSWORD' });
await page.goto('https://httpbin.org/ip');
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();
})();
因为代理是进程级参数,单个 Puppeteer 浏览器用一个 IP。要轮换就每个身份启一个新浏览器(较重),或者用逐连接换 IP 的网关来轮换。
任何会生成会话 cookie 的流程,都必须在整个生命周期保持同一 IP。在 IP-A 上生成的 cookie 突然从 IP-B 出现,会被当作会话劫持,触发重新验证或封禁。整个会话期间,每个登录账号保持一个 context(或一个浏览器)、锁定一个 sticky token。
住宅 IP 是必要但不充分。站点还会读你浏览器的 TLS/JA4 握手、HTTP/2 帧顺序、canvas、WebGL、navigator 属性。原生无头 Chromium 会泄露 navigator.webdriver = true 和一套无头指纹,再好的 IP 也拦不住。用 stealth 插件和真实启动参数缓解:
// Node: puppeteer-extra + stealth
const puppeteer = require('puppeteer-extra');
const Stealth = require('puppeteer-extra-plugin-stealth');
puppeteer.use(Stealth());
// 真实的启动参数
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--proxy-server=http://gate.jibaoproxy.com:10001',
'--disable-blink-features=AutomationControlled',
'--window-size=1920,1080',
],
});
要看清自己到底泄露了哪些信号,用自动化浏览器访问极豹免费的 JA3/JA4 指纹检测工具。握手为何被标记的深层机制,读绕过 TLS 指纹和完整的 Cloudflare 绕过配方。
headless=False 看目标实际给你的机器人展示什么。新用户注册即送5U,首次充值额外加赠,活动期间限时开放。