Puppeteer:如何存储会话(包括 cookie、页面状态、本地存储等)并稍后继续?
Posted
技术标签:
【中文标题】Puppeteer:如何存储会话(包括 cookie、页面状态、本地存储等)并稍后继续?【英文标题】:Puppeteer: how to store a session (including cookies, page state, local storage, etc) and continue later? 【发布时间】:2020-01-19 02:31:31 【问题描述】:是否可以有一个 Puppeteer 脚本打开并与页面交互,然后按原样保存该浏览器会话,并让另一个脚本加载并从那里继续?
“浏览器会话”是指当前加载的页面,包括页面状态(DOM 空间和 javascript 变量等)、cookie、本地存储、整个 shebang。基本上它需要的一切都在前一个脚本停止的地方继续。
如果没有,那么至少可以导出和导入 cookie 和本地存储吗?所以我可以重新加载特定页面并继续处理,保持所有登录或会话数据完好无损。
【问题讨论】:
关于cookies:link 另见How to manage log in session through headless chrome? 【参考方案1】:我不能肯定地说,但由于 Puppeteer“只是”Chrome DevTools 协议 (cdp) 的包装器,并且 cpd 没有执行您要求的本机“命令”,因此这是不可能的为整个shebang做这件事。
但你有选择。一个不错的选择是为下一个脚本重新使用相同的浏览器。您只需将“userDataDir”选项传递给 puppeteer.launch 命令。示例:puppeteer.launch( userDataDir: '/tmp/myChromeSession' );
。每个使用它的 puppeteer 脚本都将使用相同的浏览器,因此它们将共享“永久”cookie。 “会话”cookie(或有过期时间的)肯定会被删除,但这是 cookie 应该工作的方式。
Excerpt关于用户数据目录:
用户数据目录包含配置文件数据,例如历史, 书签、cookie 以及其他每次安装的本地状态。
尽管此参考文献没有写任何关于 Web 存储的内容,但它也保存在用户数据目录中。所以,使用这个选项你很高兴。我认为这是您情况的最佳选择。
您还有其他选择,例如仅复制 cookie 和存储(localStorage 和 sessionStorage)。
使用 puppeteer 复制 cookie
对于 puppeteer,这个过程非常痛苦:您必须指定要从中获取 cookie 的每个来源。例如,如果您的网站嵌入了第三方的东西,如 google 登录或跟踪,您必须从“google.com”、“.google.com”、“www.google.com”等复制 cookie。这非常非常愚蠢而痛苦。无论如何,要复制 cookie 来源 https://a.b.c,问题:const abcCookies = await page.cookies('https://a.b.c');
要恢复它们:await page.setCookie(...abcCookies);
。由于它们是json,您可以将它们序列化并保存到磁盘,以便以后恢复。
使用 CDP 复制 cookie
let cookies = await page._client.send('Network.getAllCookies');
参考:Network.getAllCookies
要恢复它们,请使用Network.setCookies cdp 方法。同样,您可以序列化这些 cookie 并保存到磁盘以便稍后恢复。
复制存储(localStorage 和 sessionStorage)
您可以通过const ls = await page.evaluate(() => JSON.stringify(localStorage));
和const ss = await page.evaluate(() => JSON.stringify(sessionStorage));
转移您自己的原始存储。但是,出于安全原因,您不能访问其他源存储。不知道 CDP 等价物并认为它还不存在。
网页缓存
如果您的站点有服务人员,它很可能会将内容保存在 Web Cache API 上。我不知道保存这些缓存数据是否有意义,但如果对您很重要,您也可以传输这些缓存,但不要使用 puppeteer apis 或 cdp。您必须自己使用Cache api并使用page.evaluate传输缓存。
索引数据库
如果要复制 IndexedDB 内容,可以使用 cdp IndexedDB 域方法(如“IndexedDB.requestData”)获取任何来源的数据,但不能设置/恢复此数据。 :) 但是,您可以在自己的来源中使用 page.evaluate 以编程方式恢复数据。
【讨论】:
【参考方案2】:Icrespilho的回答很有价值。他给读者留下了两个练习,我做了一个:IndexedDB。
复制 IndexedDB
他写道:
如果您想复制 IndexedDB 内容,您可以使用 cdp IndexedDB 域方法(如“IndexedDB.requestData”)获取任何来源的数据,但您无法设置/恢复此数据。 :) 但是,您可以在自己的来源中使用 page.evaluate 以编程方式恢复数据。
我已将数据读取为:
const indexedDB = await page.evaluate(async () =>
const result = ;
const databases = await window.indexedDB.databases();
const connect = (database) => new Promise(function (resolve, _)
const request = window.indexedDB.open(database.name, database.version);
request.onsuccess = _ => resolve(request.result);
);
const getAll = (db, objectStoreName) => new Promise(function (resolve, _)
const request = db.transaction([objectStoreName]).objectStore(objectStoreName).getAll();
request.onsuccess = _ => resolve(request.result);
);
for (i = 0; i < databases.length; i++)
const db = await connect(databases[i])
const dbName = db.name;
result[dbName] =
for (j = 0; j < db.objectStoreNames.length; j++)
const objectStoreName = db.objectStoreNames[j];
result[dbName][objectStoreName] = []
const values = await getAll(db, objectStoreName);
result[dbName][objectStoreName] = values;
return result;
);
我希望这对任何人都有帮助。
【讨论】:
您正在阅读IndexedDB,对吧?你是怎么设置的?以上是关于Puppeteer:如何存储会话(包括 cookie、页面状态、本地存储等)并稍后继续?的主要内容,如果未能解决你的问题,请参考以下文章
PHP cURL 没有存储会话 cookie...如何解决这个问题?
Puppeteer 类型 node_modules/puppeteer/lib/types"' 没有导出成员 'Cookie'