不下载浏览器内核:用 Playwright 直接驱动本机 Edge
做浏览器自动化时,最常见的开场白是这句:
npx playwright install
然后眼睁睁看着一百多兆的内核往下拉。磁盘紧张、网络慢、或者只是想在同事机器上临时跑个脚本,这一下就很劝退。
其实多数场景根本不需要下载。Windows 上装了 Edge,Playwright 能直接拿来用。
一、一行参数换掉整个下载
const { chromium } = require('playwright-core');
const browser = await chromium.launch({
channel: 'msedge', // 关键:走本机已安装的 Edge
headless: false,
});
channel 还可以是 chrome、chrome-beta、msedge-beta 等。Playwright 会按标准安装路径去找,找到了就直接起进程,完全不碰 ms-playwright 缓存目录。
配合 playwright-core 使用更划算——它只是驱动,不带任何内核,装完才几 MB:
npm i playwright-core
这样整个依赖体积从数百兆降到个位数。
二、想让登录态保留下来,用 persistentContext
普通 launch() 每次都是全新配置,cookie 一关就没。要保留登录状态,换成持久化上下文:
const ctx = await chromium.launchPersistentContext('./profile', {
channel: 'msedge',
headless: false,
viewport: null,
args: ['--start-maximized'],
});
./profile 是自定义的用户数据目录。第一次跑可能要手动登录一次,之后 cookie、localStorage 都留在里面,下次启动直接是登录态。
这里有个容易被忽略的选择:别用系统默认的 Edge 用户目录。原因有两个,一是浏览器正在运行时目录会被锁,二是你的日常账号和自动化脚本混在一起,出问题很难排查。单独开一个目录,干净、可丢弃、可备份。
三、四个实际踩过的坑
坑 1:同一目录只能被一个进程占用
第二次启动会直接报 profile 被锁。如果上一次的进程没退干净,报错信息还挺隐晦。排查方式是先确认没有残留进程再用:
Get-CimInstance Win32_Process -Filter "Name='msedge.exe'" |
Where-Object { $_.CommandLine -like '*my-profile*' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
按命令行里的 profile 路径过滤,比按进程名一把杀要安全得多——不会顺手把用户正在用的浏览器关掉。
坑 2:登录态不是永久的
持久化能延长会话,但不能保证一直有效。服务端会话过期、风控重置、或者清理策略变化,都会让下一次启动回到登录页。
所以脚本里不能假设"上次登录过,这次一定还登着",得显式检测:
const loggedIn = await page.evaluate(() =>
!/欢迎使用|请登录/.test(document.body.innerText.slice(0, 2000))
);
检测失败就停下来交出控制权,别硬闯。让滑块或二维码去对抗风控,最后只会把账号搞进黑名单。
坑 3:拿不到已经打开的浏览器
很多人第一反应是"能不能 attach 到用户已经开着的浏览器上"。默认不行——没有开远程调试端口就没有连接入口。
两条可行路线:一是带 --remote-debugging-port=9222 启动后 chromium.connectOverCDP();二是干脆接受"另开一个带独立 profile 的实例"。后者通常更省事,前者适合必须复用现有会话的场景。
坑 4:截图巡检比日志好用
自动化里最难查的是"页面看起来正常但就是点不到"。纯文本日志经常看不出问题,因为元素可能被遮挡、可能在 iframe 里、也可能压根没渲染出来。
定时截图落盘,出问题直接看图,比翻十行 console 快得多:
await page.screenshot({ path: 'state.png' });
四、一个够用的小结构
把状态写进 JSON,外部随时可读,特别适合长时任务:
function save(o) {
fs.writeFileSync('state.json', JSON.stringify(o, null, 2));
}
await page.goto(url);
save({ stage: 'opened', url: page.url() });
// 做动作
save({ stage: 'clicked', ts: Date.now() });
// 校验结果
save({ stage: 'verified', result });
比起让脚本一路闷头跑到底,分阶段落状态的好处是:任何一步失败,你都知道停在哪、上一阶段是否已经生效。尤其是那种"看着失败了其实成功了"的场景,重试前先读状态能避免重复提交。
五、小结
channel: 'msedge'+playwright-core,零内核下载,依赖从数百兆降到几兆launchPersistentContext+ 独立 profile,登录态可复用- 独立 profile 避免锁冲突,也避免污染日常账号
- 登录态要显式检测,失效就停,不要和风控硬碰
- 分阶段写状态 + 截图,比纯日志好排查一个数量级
这套组合对付内部工具、定时巡检、登录后抓数据这类活足够了,而且不用为"下载一个浏览器"付出额外成本。
文中代码基于 Playwright 1.6x + Windows + 本机 Edge 实测。
- 点赞
- 收藏
- 关注作者
评论(0)