使用Puppeteer实现网站登录后打开多个需认证页面及代码问题排查
问题分析与解决方案
一、登录后无法打开认证页面的原因及修复
你的代码里有几个关键问题导致后续页面无法正常加载:
1. 异步文件操作的时序问题
fs.writeFile是异步方法,你在调用它之后立刻用fs.readFileSync读取文件,这时候文件可能还没写完,导致读取到的Cookie不完整甚至为空,后续设置Cookie自然无效。
修复方式:改用同步写入或者使用fs.promises的异步写入并等待完成:
// 方式1:同步写入 const fs = require("fs"); fs.writeFileSync(cookiesFilePath, JSON.stringify(cookiesObject)); // 方式2:promise版本(推荐,更符合异步流程) const fs = require("fs").promises; await fs.writeFile(cookiesFilePath, JSON.stringify(cookiesObject));
2. 重复设置Cookie的冗余操作
当前page在登录成功后已经持有有效的会话Cookie,你没必要再从文件读取并重新设置一遍——这不仅多余,还可能导致Cookie冲突覆盖。直接跳过setCookie步骤,直接访问目标页面即可。
3. 多余的waitForNavigation导致超时
登录按钮点击后只会触发一次页面跳转,你连续调用了两次await page.waitForNavigation(),第二次调用会一直等待下一次导航事件,但此时并没有新的跳转,最终会超时,导致后续代码无法执行。
修复方式:只保留一次waitForNavigation,并指定更可靠的等待策略:
await page.click('form > fieldset > div > div.form-group.col-md-2.align-self-end.text-center > button'); // 等待网络空闲(最多2个活跃连接),确保页面完全加载 await page.waitForNavigation({ waitUntil: 'networkidle2' });
二、登录后打开多个认证页面的方法
Puppeteer中每个Page实例有独立的Cookie上下文,所以需要将登录后的会话Cookie同步到新创建的页面中。具体步骤如下:
- 登录成功后,获取当前页面的所有Cookie;
- 从同一个
browser实例创建新的Page; - 将Cookie设置到新页面;
- 用新页面访问需要认证的路径。
整合修复后的完整示例代码
const puppeteer = require('puppeteer'); const cookiesFilePath = 'cookies.json'; const fs = require("fs").promises; // 使用promise版本的fs,支持await exports.scrapper = async ()=>{ const browser = await puppeteer.launch({ headless: false, args: ['--no-sandbox'] }); const page = await browser.newPage(); await page.setDefaultTimeout(100000); // 执行登录流程 await page.goto('https://www.rasmussenreports.com/login'); await page.type('#username', 'MY_USERNAME', {delay:100}); // 直接指定输入框选择器,更准确 await page.type('#password', 'MY_PASSWORD', {delay:100}); await page.click('form > fieldset > div > div.form-group.col-md-2.align-self-end.text-center > button'); await page.waitForNavigation({ waitUntil: 'networkidle2' }); // 保存会话Cookie const cookiesObject = await page.cookies(); await fs.writeFile(cookiesFilePath, JSON.stringify(cookiesObject)); console.log('Session has been successfully saved'); // 方式1:用当前页面直接访问认证页面(无需重新设置Cookie) await page.goto('https://www.rasmussenreports.com/public_content/politics/general_politics/august_2022/inflation_crime_still_top_concerns_for_voters'); console.log("当前页面已打开目标链接"); // 方式2:创建新页面并同步Cookie,访问另一个认证页面 const newPage = await browser.newPage(); await newPage.setCookie(...cookiesObject); // 同步登录后的会话Cookie await newPage.goto('https://www.rasmussenreports.com/another-protected-page'); // 替换为实际的认证页面路径 console.log("新页面已打开目标链接"); // 可以继续创建更多页面,重复上述同步Cookie+访问的流程... // await browser.close(); // 测试阶段可以先注释,查看页面状态 }
额外注意事项
- 确保Cookie的
domain和path与目标页面匹配:登录后获取的Cookie通常是根路径(path: "/"),可以覆盖所有子页面; - 如果后续需要复用Cookie(比如下次启动脚本直接跳过登录),可以在脚本开头读取Cookie文件,设置到新页面后直接访问认证页面;
- 使用
waitUntil: 'networkidle2'比默认的load更可靠,能确保页面资源加载完成后再执行后续操作。
内容的提问来源于stack exchange,提问作者TASKMASTER
相关产品推荐
相关产品推荐

