cookies - 为什么 Puppeteer 的 setCookie() 似乎没有按预期工作?

标签 cookies google-chrome-devtools setcookie puppeteer google-chrome-headless

我试图实现的目标是存储来自网站的 cookie,然后在第二时刻使用它们。这是代码:

保存cookie:

let cookie = await page.cookies();
cookie = JSON.stringify(cookie);

fs.writeFile("cookie.txt", cookie, function(err, data){
    if (err) {
        console.log(err);
    } else {
        console.log("Successfully Written to File.");
    }
});

要读取 Puppeteer 中的 cookie:

await page._client.send("Network.clearBrowserCookies");
await injectCookiesFromFile("cookie.txt", page)
                

async function injectCookiesFromFile(file, page) {
    let cb = async function (_cookies) {
        console.log("Injecting cookies from file: %s", JSON.stringify(_cookies) );
        //await page.setCookie(..._cookies); // method 1
        await page.setCookie(_cookies); // method 2
    };

    fs.readFile(file, async function(err, data) {
        if(err) {
            throw err;
        }

        let cookies = JSON.parse(data);
        console.log(cookies);
     
        //await cb(cookies); // method 1
        for (var i = 0, len = cookies.length; i < len; i++) {
            await cb(cookies[i]); // method 2
        }
    });
}

读取 cookie 并将其保存到文件中的操作似乎有效。 但对网站没有任何影响,并且 setCookie() 方法似乎无法正常工作。有什么想法吗?

最佳答案

在开始之前,请务必注意,使用 Puppeteer 时通常不需要读取 Cookie 并将其写入文件。

Puppeteer 提供了一个高级 API,可以通过 DevTools 协议(protocol)控制 Chrome 或 Chromium,这意味着 Chromium 可以完成有关 Cookie 的大部分艰苦工作,而无需所有体力劳动。

Chromium 有一个名为 CookieMonster 的内置类它处理浏览器内 cookie 的存储、管理、检索、过期和驱逐。

换句话说,如果您尝试使用 Puppeteer 登录网站,通常可以使用以下简单示例来实现:

'use strict';

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  await page.goto('https://www.example.com/login');
  
  await page.type('#username', 'johndoe');
  await page.type('#password', 'qwerty1');
  await page.click('#submit');
  
  await page.waitForNavigation();
  
  // You are now logged in ...
  
  await browser.close();
})();

Note: Notice that I did not have to create a cookie file to read and write cookies (this is not cURL).

如果您仍决定自行管理 cookie,那么了解 Puppeteer 使用 asynchronous 至关重要。 JavaScript。

这意味着要使用 fs.writeFile 写入文件,您需要await一个Promise在回调函数中解决或拒绝,以确保文件在导航之前准备就绪。

const write_file = (file, data) => new Promise((resolve, reject) => {
  fs.writeFile(file, data, 'utf8', error => {
    if (error) {
      console.error(error);
      
      reject(false);
    } else {
      resolve(true);
    }
  });
});

fs.readFile() 也是如此。 :

const read_file = file => new Promise((resolve, reject) => {
  fs.readFile(file, 'utf8', (error, data) => {
    if (error) {
      console.error(error);
      
      reject(false);
    } else {
      resolve(data);
    }
  });
});

此外,最好先等待页面完全加载,然后再将 Cookie 写入文件,因此我建议在导航函数中使用 waitUntil: 'networkidle0' 选项:

await page.goto('https://www.example.com/login', {
  waitUntil: 'networkidle0',
});

Note: This may require you to increase the default timeout option to allow for the page to completely load.

现在我们了解了 Puppeteer 背后的一些基本概念,我们可以开始手动从文件中读取和写入 cookie。

我们可以使用page.cookies() , page.setCookie() ,和cdpSession.send()管理我们的cookie(如下例所示):

'use strict';

const fs = require('fs');
const puppeteer = require('puppeteer');

const write_file = (file, data) => new Promise((resolve, reject) => {
  fs.writeFile(file, data, 'utf8', error => {
    if (error) {
      console.error(error);
      
      reject(false);
    } else {
      resolve(true);
    }
  });
});

const read_file = file => new Promise((resolve, reject) => {
  fs.readFile(file, 'utf8', (error, data) => {
    if (error) {
      console.error(error);
      
      reject(false);
    } else {
      resolve(data);
    }
  });
});

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const client = await page.target().createCDPSession();
  
  // Open First Page
  
  await page.goto('https://www.example.com/', {
    waitUntil: 'networkidle0',
  });
  
  // Write All Cookies to File
  
  await write_file('cookies.txt', JSON.stringify(await page.cookies()));
  
  // Open Second Page
  
  await page.goto('https://www.example.com/next-page', {
    waitUntil: 'networkidle0',
  });
  
  // Clear Browser Cookies
  
  await client.send('Network.clearBrowserCookies');
  
  // Read All Cookies from File
  
  await page.setCookie(...JSON.parse(await read_file('cookies.txt') || '[]'));
  
  await browser.close();
})();

关于cookies - 为什么 Puppeteer 的 setCookie() 似乎没有按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49214208/

相关文章:

禁用cookie的php setcookie行为

php - php 7.3 中 setcookie() 的正确语法是什么?

php - 在哪里存储登录尝试和当前登录状态、cookie 或 session ?

c# - ASP.NET Core Identity 中的两个身份验证 cookie

javascript - 关闭 Internet Explorer 后 Cookie 为空

javascript - chrome 72 更改了 sourcemap 行为

php - 如何在查询时区分管理员和用户?

javascript - 从 Devtools 窗口将 Chrome 选项卡置于前台

php - Laravel/PHP dd() 在 Chrome 开发者工具中显示非结构化数组

jakarta-ee - 当我们通过 Facebook 登录时如何删除 Facebook Cookie