Playwright 复用本机 Chrome:省掉 170MB 下载,以及三个 cookie 注入坑
在服务器或 CI 里跑 Playwright,最容易卡住的一步不是写脚本,而是浏览器二进制。默认安装会拉一个约 170MB 的 Chromium,网络一抖就失败。其实机器上已经有 Chrome 时,完全可以复用它。
一、优先用系统浏览器
playwright-go 的 Launch 支持 ExecutablePath。写一个探测函数,按平台找:
func chromePath() string {
for _, p := range []string{
"/usr/bin/chromium",
"/usr/bin/google-chrome",
"/snap/bin/chromium",
} {
if _, err := os.Stat(p); err == nil {
return p
}
}
for _, base := range []string{
os.Getenv("ProgramFiles"),
os.Getenv("LOCALAPPDATA"),
} {
if base == "" {
continue
}
p := filepath.Join(base, "Google", "Chrome", "Application", "chrome.exe")
if _, err := os.Stat(p); err == nil {
return p
}
}
return ""
}
找到就传进去,找不到再回落到 Playwright 自带 Chromium:
opts := playwright.BrowserTypeLaunchOptions{Headless: playwright.Bool(true)}
if p := chromePath(); p != "" {
opts.ExecutablePath = playwright.String(p)
}
browser, err := pw.Chromium.Launch(opts)
注意:driver 仍然要装。省掉的是浏览器本体,不是 Node 侧的 driver。
二、__Host- 前缀的 cookie 会导致整批注入失败
把登录态导出后塞进新 context 是常见做法。但一批 cookie 里只要有一个不合法,AddCookies 会整体报错:
playwright: Protocol error (Storage.setCookies): Invalid cookie fields
罪魁祸首通常是 __Host-session 这类名字。按规范,__Host- 前缀必须满足三条:不带 domain、path 为 /、标记 Secure。从浏览器导出时它带着 domain,直接回填就会被拒。
解决办法是改用 url 表达,让 Playwright 自己推导 domain 与 path:
if strings.HasPrefix(c.Name, "__Host-") {
item.URL = playwright.String("https://" + host + "/")
item.Secure = playwright.Bool(true)
continue
}
item.Domain = playwright.String(c.Domain)
item.Path = playwright.String(c.Path)
三、批量失败要退化成逐个注入
即使修好 __Host-,生产环境的 cookie 依然可能有个别异常。批量注入失败时不要直接放弃,逐个再试一遍,跳过坏的:
func addCookies(ctx playwright.BrowserContext, cookies []playwright.OptionalCookie) error {
if len(cookies) == 0 {
return nil
}
if err := ctx.AddCookies(cookies); err == nil {
return nil
}
ok := 0
var firstErr error
for _, c := range cookies {
if err := ctx.AddCookies([]playwright.OptionalCookie{c}); err != nil {
if firstErr == nil {
firstErr = fmt.Errorf("cookie %s: %w", c.Name, err)
}
continue
}
ok++
}
if ok == 0 && firstErr != nil {
return firstErr
}
return nil
}
这样即使丢掉两三个 cookie,登录态通常还能用。
四、多子域同名 cookie 别按 name 去重
如果目标站点跨多个子域,同名 cookie 会同时出现好几份,值还不一样。按 name 去重只保留最后一条,很可能留下的是过期副本。
正确做法是按 (domain, path, name) 三元组区分,或者干脆不去重,交给浏览器自己判定优先级。
小结
| 问题 | 处理 |
|---|---|
| 不想下载 170MB Chromium | ExecutablePath 指向系统 Chrome |
Invalid cookie fields |
__Host- 前缀改用 url 表达 |
| 一个坏 cookie 拖垮全部 | 批量失败后逐个注入 |
| 同名 cookie 取值错乱 | 按 domain + path + name 去重 |
复用系统浏览器除了省下载,还有个隐性好处:指纹更接近真实用户,不容易被判定为机器人。代价是版本不受控,升级 Chrome 后要及时回归。
- 点赞
- 收藏
- 关注作者
评论(0)