跳到正文
当下的七炎
返回

Playwright 接管本地 Edge:复用登录态操作真实网页

编辑文章

前两天折腾了一个挺有意思的事情。

不是让 Playwright 自己启动一个全新的浏览器,而是直接连接到我本地已经打开、已经登录的 Edge 浏览器,然后继续操作里面的网页。

这个需求其实非常真实。

很多时候我们并不是在做自动化测试,而是在处理一些日常工作:

这次我最终跑通了整个流程:

Playwright → 连接本地 Edge → 复用登录态 → 打开 NodeLoc → 进入帖子 → 自动发表评论。

Image

过程中踩了几个坑,顺手记录一下。


为什么不用 Playwright 自己启动浏览器?

平时大家写 Playwright,大多都是这样开始:

const { chromium } = require('playwright');

const browser = await chromium.launch();

这样当然没问题。

但有一个明显缺点:

这是一个全新的浏览器环境。

意味着:

如果只是自动化测试,这很合适。

但如果你想操作一个真实网站、真实账号、真实页面,就会比较麻烦。

例如:

往往都需要重新登录。

而我的浏览器里其实早就已经登录好了。

既然如此,为什么不直接让 Playwright 接管当前浏览器呢?

于是思路就变成了:

浏览器开启远程调试

获取 CDP 地址

Playwright 连接已有浏览器

复用登录态继续操作

第一个坑:PowerShell 启动命令报错

一开始我是这样启动 Chrome 的:

"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222

结果直接报错。

后来才反应过来:

这是 PowerShell,不是 CMD。

PowerShell 中执行带路径的程序,需要使用调用运算符:

&

正确写法:

& "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222

如果是 Edge:

& "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --remote-debugging-port=9222

虽然是个小坑,但第一次碰到确实容易卡住。


第二个坑:9222 端口打不开

启动后访问:

http://127.0.0.1:9222/json/version

结果提示:

127.0.0.1 拒绝了连接请求

最开始我还怀疑:

后来发现问题其实更简单:

浏览器原本就在后台运行。

新的启动参数根本没有生效。

也就是说:

你以为启动了一个带远程调试端口的浏览器。

实际上系统只是复用了原来的浏览器进程。


解决办法

方案一:关闭所有浏览器进程

彻底退出 Chrome 或 Edge 后重新启动。


方案二:单独创建调试配置

我后来更推荐这种方式:

& "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
  --remote-debugging-port=9222 `
  --user-data-dir="$env:TEMP\edge-cdp"

这样会启动一个独立的浏览器配置目录。

成功率更高。


获取 CDP 地址

远程调试启动成功后,访问:

http://127.0.0.1:9222/json/version

会返回类似:

{
  "webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/browser/xxxxxxxx"
}

其中最重要的就是:

webSocketDebuggerUrl

Playwright 连接本地浏览器

代码非常简单:

const { chromium } = require('playwright');

async function main() {
  const browser = await chromium.connectOverCDP(
    'ws://127.0.0.1:9222/devtools/browser/xxxx'
  );

  const context = browser.contexts()[0];

  const page = await context.newPage();

  await page.goto('https://www.nodeloc.com/', {
    waitUntil: 'domcontentloaded',
    timeout: 60000,
  });

  console.log(await page.title());

  await browser.close();
}

main();

实际上也可以直接写:

const browser = await chromium.connectOverCDP(
  'http://127.0.0.1:9222'
);

Playwright 会自动获取 WebSocket 地址。


真正让我觉得成功的瞬间

代码跑完并不稀奇。

真正让我觉得这事成了,是看到网页打开之后:

登录状态还在。

论坛账号还是登录状态。

Cookie 还在。

LocalStorage 也还在。

这时候的感觉完全不一样。

因为:

它已经不是在模拟一个新的浏览器访问网站。

而是在接管我正在使用的浏览器会话。


复用登录态到底有多省事?

如果使用传统 Playwright:

启动浏览器

打开登录页

输入账号密码

处理验证码

保持会话

执行任务

而接管本地浏览器以后:

连接浏览器

直接开始操作

中间所有登录相关步骤全部省掉。


我这次实际完成了什么?

整个流程如下:

连接本地 Edge

复用论坛登录状态

打开目标帖子

定位回复框

输入评论内容

点击发送

回复成功

提交完成后页面 URL 发生变化。

说明回复确实已经提交到真实网站。

不是模拟成功。

是真成功。


这种方案适合哪些场景?

1. 已登录网站操作

例如:

最怕重新登录。

这种方式特别适合。


2. 半自动化流程

例如:

人工登录

人工过验证码

脚本接管

自动执行后续任务

这是现实中最常见的场景。


3. 运营类工作

例如:

都很方便。


4. 真实环境调试

有些问题:

新浏览器复现不了
真实浏览器能复现

这时候 CDP 接管会非常好用。


几个必须注意的问题

1. 不要暴露调试端口

远程调试权限非常高。

能连接的人基本就能控制你的浏览器。

因此建议:

只监听本机
不要映射公网
不要随便共享地址

2. 真实环境意味着真实后果

这不是测试环境。

你点点赞按钮:

真的会点赞。

你发评论:

真的会发出去。

因此最好先检查状态:

await expect(
  page.getByRole('button', { name: '发送' })
).toBeVisible();

确认无误再执行点击。


3. 不要把密码写进脚本

既然已经能复用登录态:

就没必要再保存账号密码。

安全性反而更高。


4. 优先使用语义化定位

相比这种:

#root > div > div:nth-child(3) > button

我更推荐:

getByRole()
getByText()
getByLabel()

代码更稳定。

页面改版也更不容易失效。


一点感受

以前我一直把 Playwright 当成测试工具。

但这次折腾完之后,我更愿意把它理解成:

一个能够接入真实浏览器会话的自动化控制器。

尤其是在需要:

的时候,体验非常顺畅。

很多自动化问题,本质上并不是操作网页难。

而是登录、会话、验证码太麻烦。

而 CDP 接管浏览器,恰好绕开了这些问题。


总结

如果你需要操作一个已经登录的网站,又不想重新实现整套登录流程,可以试试下面这套方案:

浏览器开启远程调试端口

获取 CDP 地址

Playwright connectOverCDP()

连接已有浏览器会话

新开标签页执行自动化任务

这套流程一旦跑通,你会发现很多原本麻烦的事情突然变简单了。

至少对我来说,它比每次从一个全新的浏览器开始要顺手得多。


编辑文章
分享这篇文章:

评论

使用 GitHub 账号登录后即可评论


上一篇
Playwright 接管本地 Edge,交给AI来做
下一篇
chagpt账号注册