在puppeteer中加载页面之前设置localstorage项目?

chr*_*fee 7 javascript local-storage puppeteer

如果你没有设置JWT_TOKEN,我们有一些路由逻辑可以将你踢到主页...我想在页面加载之前/在调用js之前设置它.

我该怎么做呢 ?

Kur*_*gor 22

2021 年,它可以使用以下代码:

// store in localstorage the token
   await page.evaluateOnNewDocument (
     token => {
       localStorage.clear();
       localStorage.setItem('token', token);
     }, 'eyJh...9_8cw');
   // open the url
 await page.goto('http://localhost:3000/Admin', { waitUntil: 'load' });
Run Code Online (Sandbox Code Playgroud)

不幸的是,第一条评论的下一行不起作用

await page.evaluate(() => {
  localStorage.setItem('token', 'example-token'); // not work, produce errors :(
});
Run Code Online (Sandbox Code Playgroud)


Eve*_*tss 16

你必须注册这样的localStorage项目:

await page.evaluate(() => {
  localStorage.setItem('token', 'example-token');
});
Run Code Online (Sandbox Code Playgroud)

你应该在页面之后进行page.goto- 浏览器必须有一个url来注册本地存储项目.在此之后,再次输入相同的页面,这个时间令牌应该在页面加载之前.

这是一个完整的例子:

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

const html = `
<html>
  <body>
    <div id="element"></div>

    <script>
      document.getElementById('element').innerHTML = 
        localStorage.getItem('token') ? 'signed' : 'not signed';
    </script>
  </body>
</html>`;

http
  .createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write(html);
    res.end();
  })
  .listen(8080);

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('http://localhost:8080/');

  await page.evaluate(() => {
    localStorage.setItem('token', 'example-token');
  });

  await page.goto('http://localhost:8080/');

  const text = await page.evaluate(
    () => document.querySelector('#element').textContent
  );

  console.log(text);
  await browser.close();

  process.exit(0);
})();
Run Code Online (Sandbox Code Playgroud)


mar*_*don 11

Puppeteer 的 GitHub 问题中对此有一些讨论。

您可以在域上加载一个页面,设置您的 localStorage,然后在准备好 localStorage 的情况下转到您要加载的实际页面。您还可以拦截第一个 url 加载以立即返回而不是实际加载页面,这可能会节省大量时间。

const doSomePuppeteerThings = async () => {
  const url = 'http://example.com/';
  const browser = await puppeteer.launch();
  const localStorage = { storageKey: 'storageValue' };
  setDomainLocalStorage(browser, url, localStorage);

  const page = await browser.newPage();
  // do your actual puppeteer things now
};

const setDomainLocalStorage = async (browser, url, values) => {
  const page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('request', r => {
    r.respond({
      status: 200,
      contentType: 'text/plain',
      body: 'tweak me.',
    });
  });
  await page.goto(url);
  await page.evaluate(values => {
    for (const key in values) {
      localStorage.setItem(key, values[key]);
    }
  }, values);
  await page.close();
};
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您的回答,这可能是我找到的最好的解决方案。通过将“evaluate”行更改为“await page.setCookie(...cookies)”,我也可以轻松地对 cookie 进行调整。很高兴看到这个答案也来自一位主要的木偶开发者。 (2认同)

Rém*_*ski 6

无需加倍,goTo这将起作用:

const browser = await puppeteer.launch();
browser.on('targetchanged', async (target) => {
  const targetPage = await target.page();
  const client = await targetPage.target().createCDPSession();
  await client.send('Runtime.evaluate', {
    expression: `localStorage.setItem('hello', 'world')`,
  });
});
// newPage, goTo, etc...
Run Code Online (Sandbox Code Playgroud)

改编自 lighthouse doc for puppeteer 做类似的事情:https : //github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md


And*_*Kim -5

尝试添加额外的脚本标签。例子:

假设您有一个main.js包含路由逻辑的脚本。

然后是setJWT.js包含您的令牌逻辑的脚本。

然后在加载这些脚本的 html 中按以下方式对它们进行排序:

<script src='setJWT.js'></script>
<script src='main.js'></script>
Run Code Online (Sandbox Code Playgroud)

这仅适用于页面的初始启动。

然而,大多数路由库通常都有一个事件挂钩系统,您可以在路由渲染之前挂钩该系统。我会将逻辑存储setJWT在该回调中的某个位置。

  • 这个答案与 Puppeteer 无关:( (3认同)