Playwright 登录态管理实践:从二维码登录到定时任务
背景
在浏览器自动化项目里,登录往往比业务逻辑更脆弱。最初我习惯把账号密码写进环境变量,每次任务启动都重新登录。这样虽然能跑,但会带来三个问题:密码长期暴露在配置中、频繁登录容易触发风控、验证码或二维码一旦出现,无人值守任务就会直接失败。
后来我把流程改成“人工登录一次,程序复用登录态”,稳定性明显提升。本文以 Playwright 为例,整理一套可复用的登录态管理方案。
为什么不直接保存账号密码
账号密码是长期凭证,而浏览器登录态是短期会话。把密码交给定时任务,相当于让每个脚本都拥有完整账号权限;一旦日志、配置文件或备份泄露,影响范围很大。
更合理的做法是:
- 由人工完成一次扫码或验证码登录;
- 程序只保存浏览器上下文中的 Cookie 和 localStorage;
- 后续任务复用这份状态,失效时再提示人工重新登录。
保存登录态
Playwright 的 storageState 可以把 Cookie、localStorage 等状态序列化到文件。登录成功后保存一次即可:
const { chromium } = require("playwright");
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://example.com/login");
// 等待用户扫码或完成登录
await page.waitForURL("https://example.com/dashboard", { timeout: 300000 });
await context.storageState({ path: "state.json" });
await browser.close();
无人值守任务启动时,直接加载这份状态:
const context = await browser.newContext({
storageState: "state.json",
});
const page = await context.newPage();
await page.goto("https://example.com/dashboard");
这样既不需要在脚本里保存密码,也避免了每次启动都走登录流程。
不要只看页面有没有跳转
登录态是否有效,不能只靠“页面能打开”判断。很多站点在未登录时也会返回 200,只是内容变成登录提示。更可靠的方式是调用一个需要登录的接口,检查状态码或返回结构。
例如在页面上下文中请求用户信息接口:
const response = await context.request.get(
"https://example.com/api/me"
);
if (response.status() === 401) {
throw new Error("登录态已过期,请重新扫码");
}
把“登录态检测”和“业务执行”分开,失败时就能明确区分是网络问题、接口变更,还是会话过期。
定时任务中的工程化处理
在定时任务里,我通常把流程拆成四步:
- 加载状态文件;
- 校验会话;
- 执行业务;
- 记录结果并按需通知。
伪代码如下:
async function runTask() {
const context = await browser.newContext({
storageState: "state.json",
});
const me = await context.request.get("/api/me");
if (me.status() === 401) {
await notify("登录态过期,请重新扫码");
return;
}
await doBusiness(context);
await notify("任务执行成功");
}
状态失效并不可怕,可怕的是脚本把它当成业务失败反复重试,最后触发风控。因此需要把“需要人工重新登录”定义为一种独立状态。
安全注意事项
state.json 本质上就是一份凭证,应该按敏感文件管理:
- 不要提交到 Git;
- 文件权限设置为仅当前用户可读;
- 不要通过聊天、日志或截图外发;
- 生产环境放在受控目录,并做好备份与轮换;
- 条件允许时,给自动化账号使用独立身份,避免和主账号混用。
如果服务还需要对外提供接口,建议在会话之外再加一层独立的协议 Token,形成“会话 + Token”的双重校验。
小结
登录态复用并不复杂,关键是把它当成一项工程能力,而不是临时脚本:
- 人工登录一次,程序保存
storageState; - 每次任务先校验会话,再执行业务;
- 会话过期时明确提示人工处理;
- 状态文件按凭证级别保护。
这样既能减少重复登录,也能让自动化任务在长期运行中更稳定、更容易维护。
- 点赞
- 收藏
- 关注作者
评论(0)