如何在 Playwright 中使用代理:基本指南
Scraping and Proxy Management Expert
TL;DR:
- Playwright通过一个配置选项驱动代理。
proxy参数接受服务器、用户名和密码,并且在启动本地浏览器或连接远程浏览器时都可以使用相同的格式。 - 住宅出口使无头流量看起来像是人为的。 数据中心IP范围和默认的自动化指纹是公共网站首先检查的两个信号;通过真实的住宅地址路由可以消除第一个。
- 无刮取浏览器使用Chrome开发者工具协议。 Playwright通过
chromium.connectOverCDP(endpoint)连接到它,因此住宅代理和反检测都在云端运行,而你的脚本保持为普通的Playwright。 proxyCountry固定出口区域;sessionName加上sessionTTL在浏览时保持一个IP。 地理定位和粘性会话是连接字符串上的查询参数,而不是额外的应用代码。- 并行运行可以通过独立会话扩展。 同时打开多个连接,每个连接都有自己的住宅IP,没有并发座位的上限。
- 免费开始。 新的Scrapeless帐户包括免费的刮取浏览器运行时——请在app.scrapeless.com注册。
介绍:Playwright代理,以及原始配置的局限
Playwright通过单一API驱动Chromium、Firefox和WebKit,并且其自动等待功能使得导航不像旧一代自动化工具那样脆弱。虽然如此,仍有两件事情会导致Playwright脚本被阻止。浏览器会提供一个检测脚本可以读取的自动化指纹,并且它从主机机器拥有的IP连接——通常是一个云端或数据中心地址,这些地址被公共网站限流或地理限制。一个住宅代理解决了网络部分的问题;一个反检测浏览器解决了指纹部分的问题。
本指南首先介绍Playwright自己的代理支持,因为这是每个代理接入的选项。然后,它显示原始代理配置在哪些地方遇到障碍,以及如何将更复杂的情况交给Playwright通过同一协议连接的云浏览器。
前提条件
- Node.js 18或更高版本
- 一个Scrapeless账户和API密钥——请在app.scrapeless.com注册
- 已安装Playwright(
npm install playwright) - 对npm和Node.js环境变量有基本的了解
安装
1. 将Playwright添加到你的项目中
如果你还没有Playwright,请安装它:
bash
npm install playwright
这将引入适用于所有三个浏览器引擎的Playwright库。
2. 设置你的Scrapeless API密钥
将密钥存储为环境变量,以便它不会出现在源代码控制中:
bash
export SCRAPELESS_API_KEY="your_api_key_here"
3. 无需额外的SDK包装
Playwright通过Chrome开发者工具协议连接到Scrapeless刮取浏览器,因此除了Playwright本身之外没有额外的包需要安装。
配置Playwright的内置代理
Playwright在launch()和newContext()中接受代理设置。将server指向你的代理网关并传递凭证:
javascript
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
proxy: {
server: 'http://your-proxy-host:8080', // 你的代理网关
username: 'your-proxy-user',
password: 'your-proxy-pass',
},
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
})();
这就是整个库级别的接口,它在Chromium、Firefox和WebKit中工作相同。它不做的两件事是:假设你已经有了一组住宅地址来指向server,并且它保留了浏览器的自动化指纹。原始的代理配置将你的流量移至新IP;它不会改变页面如何读取客户端。
在免费计划中获取你的API密钥:app.scrapeless.com
原始代理配置的局限——指纹和IP来源
两个缺口位于 launch({ proxy }) 和一个自动化运行之间,公共网站提供清晰的服务:获取和轮换真正的住宅池,以及浏览器到达后呈现的指纹。Scrapeless Scraping Browser 解决了这两个缺口。它是一个针对网络爬虫和AI代理的反检测云浏览器,并且因为它支持Chrome DevTools协议,Playwright只需一行代码即可附加。在Playwright中特别提供:
- 195多个国家的住宅出口节点,自动化指纹在云端处理。
- 云端JavaScript渲染 — 远程浏览器执行页面,因此工作离开了您的机器。
- 地理定位和固定会话作为连接参数 —
proxyCountry、sessionName和sessionTTL附带在端点字符串中。 - 没有并发座位限制 — 按使用付费,打开所需的任意数量的会话。
连接字符串将您的密钥作为 token 参数传递;docs.scrapeless.com 的文档列出了所有选项。在app.scrapeless.com上免费计划获取您的API密钥。
通过CDP连接Playwright
构建WebSocket端点,然后使用 chromium.connectOverCDP() 连接。从这里开始,便是普通的Playwright — 代理和指纹已经在远程浏览器上应用:
javascript
const { chromium } = require('playwright');
const token = process.env.SCRAPELESS_API_KEY;
const params = new URLSearchParams({
token,
proxyCountry: 'US', // 固定住宅出口地区
sessionTTL: '300', // 会话保持活跃300秒
});
const wsEndpoint = `wss://browser.scrapeless.com/api/v2/browser?${params.toString()}`;
(async () => {
const browser = await chromium.connectOverCDP(wsEndpoint);
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log('标题:', await page.title());
// 确认出口是住宅IP,而不是主机机器的IP
const ipPage = await context.newPage();
await ipPage.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded' });
console.log('出口:', await ipPage.evaluate(() => document.body.innerText));
await browser.close();
})();
固定国家并重用一个IP
地理定位是 proxyCountry 参数。固定性是 sessionName 加上一个活跃的 sessionTTL:在窗口内重用相同名称,每次导航都从相同的住宅IP离开,这有助于保持一个身份的登录流程。
javascript
const { chromium } = require('playwright');
const token = process.env.SCRAPELESS_API_KEY;
function endpoint({ country, session }) {
const params = new URLSearchParams({
token,
proxyCountry: country,
sessionName: session, // 同名 + 活跃TTL = 同一出口IP
sessionTTL: '300',
});
return `wss://browser.scrapeless.com/api/v2/browser?${params.toString()}`;
}
(async () => {
const browser = await chromium.connectOverCDP(endpoint({ country: 'US', session: 'demo-session' }));
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded' });
console.log('第一次:', await page.evaluate(() => document.body.innerText));
await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded' });
console.log('第二次:', await page.evaluate(() => document.body.innerText));
await browser.close();
})();
并行运行会话
每个连接都是独立的,因此一个工作池是 Promise.all,跨多个具有不同会话名称的端点。每个主机保持三次并发以保持礼貌:
javascript
const { chromium } = require('playwright');
const token = process.env.SCRAPELESS_API_KEY;
function endpoint(session) {
const params = new URLSearchParams({ token, proxyCountry: 'US', sessionName: session, sessionTTL: '180' });
return `wss://browser.scrapeless.com/api/v2/browser?${params.toString()}`;
}
async function fetchIp(session) {
const browser = await chromium.connectOverCDP(endpoint(session));
try {
const page = await browser.newContext().then(c => c.newPage());
await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded' });
return { session, ip: JSON.parse(await page.evaluate(() => document.body.innerText)).ip };
} finally {
await browser.close();
}
}
(async () => {
const workers = ['worker-1', 'worker-2', 'worker-3'];
```javascript
const results = await Promise.all(workers.map(fetchIp));
console.log(results);
})();
你得到的结果
每个会话报告一个独特的住宅出口,而一个粘性的会话则报告同一个出口两次。上面的并行运行为每个工作者返回一条记录:
javascript
// 示例样本 — 模式是确切的;IP值是示例性的,并且根据会话而变化。
[
{ "session": "worker-1", "ip": "72.188.194.89" },
{ "session": "worker-2", "ip": "172.56.218.152" },
{ "session": "worker-3", "ip": "73.135.52.138" }
]
模式说明:
proxyCountry: 'US'将每个出口固定到美国的住宅地址;更改代码以目标其他区域。- 在一个
sessionName和一个有效的sessionTTL内,IP 在导航过程中保持不变;新的名称会调用一个新的地址。 - 选择器必须匹配目标网站当前的标记 — 当DOM发生变化时要收紧它们。
- 远程浏览器默认渲染JavaScript,因此在你读取DOM之前,客户端内容已经存在。
故障排除
连接在长时间运行中途掉线
原因: sessionTTL 在工作流程完成之前过期。
解决方法: 提前设置 sessionTTL,以涵盖整个流程 — 它是会话的生命周期(以秒为单位),因此可以将其设置为您期望的最长导航链。
网站仍然显示“访问被拒绝”页面
原因: 一个干净的住宅IP并不是唯一的信号;一个直接跳转到深层URL的冷会话仍然看起来是自动化的。
解决方法: 通过在同一上下文中先加载网站的主页来加热会话,将 proxyCountry 固定到与受众匹配的区域,并提供现实的上下文选项(userAgent,Accept-Language)。
提取返回空字段
原因: 选择器不再与渲染的标记匹配。
解决方法: 重新检查页面并收紧选择器;保护可选字段,以便缺失的元素返回null而不是抛出异常。
结论:一个不干扰应用代码的代理层
一个代理的Playwright运行简化为几个步骤:建立端点、通过CDP连接、固定国家,并编写您已经了解的同样的Playwright。原生 launch({ proxy }) 适用于您拥有代理池的情况;爬虫浏览器则适用于您需要真正的住宅出口和可以维持的指纹的情况。使用 proxyCountry 固定出口,保持一个身份与 sessionName 加上有效的 sessionTTL,每个主机的并发保持在三次,并将缺失的字段视为可为null。有关轮换策略的更广泛观点,请参见 best-rotating-proxies-2026。
准备好使用Playwright和代理进行大规模自动化吗?
加入我们的社区,领取免费计划并与构建Playwright自动化的开发者联系:Discord · Telegram。
在 app.scrapeless.com 注册以获得免费的爬虫浏览器运行时,查看 定价,并根据您的自动化需求调整上述模式以适应区域和网站。
常见问题
问:使用Playwright进行爬虫是合法的吗?
抓取公开可见的数据在广义上是允许的,但规则因司法管辖区和网站服务条款而异。请审查目标的条款,避免抓取您没有授权使用的登录后的数据,并就任何敏感信息咨询法律顾问。
问:我需要代理吗?
每当目标屏蔽数据中心IP或应用地域限制时,您都需要一个代理,这涵盖了大多数公共网站。住宅出口让请求像普通用户流量一样到达;没有它,云IP很容易被阻挡。
问:我看到“访问被拒绝”页面 — 我该如何获得干净的渲染?
首先在同一上下文中加载网站的主页以加热会话,将 proxyCountry 固定到适合受众的区域,并设置现实的上下文选项,如 userAgent 和 Accept-Language。从冷上下文直接访问深层URL是常见的触发因素。
问:我可以同时运行多个Playwright会话吗?
可以。每个CDP连接是独立的,并且提取自己的住宅IP,因此工作者池是 Promise.all 在多个端点上,具有不同的 sessionName 值。保持每个主机的并发不超过三次,以保持在礼貌的限制内。
问:如何切换出口国家?
更改 proxyCountry 参数并打开新的连接。会话创建时国家被固定,因此不同的区域意味着要新建一个端点字符串,而不是会话中期更改。
问:这在JavaScript重的网站上有效吗?
是的。远程浏览器在您查看页面之前执行该页面,因此在 page.goto() 解析时,客户端呈现的内容已经在 DOM 中。对于网络连接从未闲置的网站,使用 waitUntil: 'domcontentloaded' 加上短暂的稳定。
问:当网站的标记发生更改时会发生什么?
与特定类或结构绑定的选择器在网站进行重新设计时会断裂。使用可用的最稳定信号进行锚提取——即数据属性或经过哈希处理的 CSS 类的持久 URL 模式——并在字段开始返回为空时重新检查选择器。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



