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

时间:2018-03-10 21:28:34

标签: 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
            }
        });
    }
    &#13;
    &#13;
    &#13;

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

1 个答案:

答案 0 :(得分:7)

开始之前,请务必注意,使用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();
})();
  

注意:请注意,我不必创建一个cookie文件即可读写cookie(不是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',
});
  

注意:这可能需要您增加默认的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();
})();