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

Gré*_*ire 5 cookies setcookie google-chrome-devtools google-chrome-headless puppeteer

我想要实现的目标是存储来自网站的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.");
        }
    });
    Run Code Online (Sandbox Code Playgroud)

  • 阅读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
            }
        });
    }
    Run Code Online (Sandbox Code Playgroud)

在文件上读取和保存cookie的操作似乎有效.但是对网站没有任何影响,似乎setCookie()方法没有正常工作.有什么想法吗?谢谢您的帮助.

Gra*_*ler 8

在开始之前,请务必注意,使用Puppeteer时通常不需要将cookie写入文件中。

Puppeteer提供了一个高级API,可通过DevTools协议控制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();
})();
Run Code Online (Sandbox Code Playgroud)

注意:请注意,我不必创建cookie文件来读写cookie(不是cURL)。

如果您仍然自己管理cookie,那么了解Puppeteer利用异步 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);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

同样适用于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);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

另外,在将Cookie写入文件之前,等待页面完全加载是一个好主意,因此,我建议waitUntil: 'networkidle0'在导航功能中使用该选项:

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

注意:这可能需要您增加默认timeout选项,以允许页面完全加载。

现在,我们了解了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();
})();
Run Code Online (Sandbox Code Playgroud)