不碰账号密码、不碰 2FA,把本机 Chrome 已登录会话复用到 Playwright,驱动填表/抓数/点按钮。核心三步:Keychain 取 Chrome Safe Storage 口令 → PBKDF2(saltysalt, 1003 轮) 派生密钥 → AES-128-CBC(openssl) 解开 v10 cookie;再用 launchPersistentContext + addCookies 注入全新上下文。
1. cookie 从哪来、怎么解
Chrome 在 macOS 把 cookie 加密存在 ~/Library/Application Support/Google/Chrome/Default/Cookies(SQLite,cookies 表)。加密密钥不落盘,存在系统 Keychain 的 Chrome Safe Storage 项里。
解密函数(脚本 dump_cookies.py,共 88 行)核心是这段:
python
KEY = hashlib.pbkdf2_hmac("sha1", KEYCHAIN_PW, b"saltysalt", 1003, 16)
IV = b" " * 16 # 16 个空格
# 去 v10 / v11 三字节前缀
body = enc[3:] if enc[:3] in (b"v10", b"v11") else enc
if enc[:3] == b"v20":
raise RuntimeError("app-bound encryption (v20) not supported")
# openssl aes-128-cbc -d -nopad 解密,再去 PKCS7
要点:
- 派生算法固定:
PBKDF2(HMAC-SHA1, 口令,saltysalt, 1003, dklen=16); - IV 是 16 个空格 (
b" " * 16),不是随机值; - 前缀
v10/v11是常规加密,v20是 app-bound encryption,这条路不通,需另想办法; - Chrome 130+ 在明文前加 32 字节 domain hash,要剥掉才是真值;
- 解密用系统
openssl即可,无需装pycryptodome。
2. 注入:全新上下文 + 去重
千万不要直接拷贝整个 Chrome profile------实测密钥不匹配会让所有 cookie 解密失败、瞬间全退登录态。正确姿势:
js
const ctx = await chromium.launchPersistentContext('/tmp/wb-pw-profile', {
channel: 'chrome', headless: true,
});
const cookies = raw.filter(/* 按 name|domain|path 去重 */);
cookies.forEach(c => c.sameSite = c.sameSite || 'Lax');
await ctx.addCookies(cookies);
要点:
- 用
launchPersistentContext起全新临时目录,不是用户日常 Chrome; - 注入前按
name|domain|path三元组去重,重复 cookie 会让站点认不出登录态; sameSite字段补成合法值(Lax/Strict),否则部分站点读不到;- 验证登录看页面文字里的用户名,不要只看 HTTP 200------状态码 200 也可能是跳到了登录页。
3. 表单填表的可靠打法(真实踩坑数字)
| 控件 | 正确做法 | 错法(静默失败) |
|---|---|---|
Element UI el-cascader |
hover 父节点展开子列,再点叶子 .el-cascader-node__label |
点父节点复选框 → 一次误勾 88 项 |
Quill 富文本 |
click→Meta+A→删除→keyboard.insertText |
找 textarea(不存在);fill() 无效 |
contenteditable |
同上,用 insertText 而非 fill |
native setter + dispatchEvent → model 不更新 |
antd RangePicker |
面板点选、跨年双向翻页;无固定期限填 2099-12-31 |
fill() 写进去但 model 不变 |
| 提交按钮文案夹空格 | innerText.replace(/\s+/g,'') 再比 + 坐标点击 |
hasText('提交') → 超时 45s |
| Nuxt/Vue SPA | 抓 Vue Router 一次拿 128 条路由 | 猜 URL(/user/123)→ 全 404 |
通用纪律:行内逐项保存的表单,输入完至少等 1.2--1.8 秒再点保存(实测 0.9 秒静默失败、1.5 秒才稳);最后必须重载页面反查值真的落库。
4. 复现清单

| 文件 | 行数 | 作用 |
|---|---|---|
dump_cookies.py |
88 | 从 Default/Cookies 解密指定域 cookie → JSON |
chrome-session-reuse SKILL.md |
173 | cookie 解密 + Playwright 注入 + 表单打法全集 |
| 注入上下文 | --- | launchPersistentContext + addCookies + sameSite 修正 |