Puppeteer会检测新标签页何时打开

时间:2018-03-01 12:44:13

标签: javascript google-chrome puppeteer

一个非常简单的问题。

在某些情况下,我的网络应用会打开一个新标签页。 但是当我尝试获取所有标签(await browser.pages())时,我只返回一个初始页面。

如何在我的代码中获取新页面的对象?

当您没有使用await browser.newPage()的木偶操纵者创建新标签时会发生这种情况,但是当您执行以下操作时:

await (await browser.pages())[0].evaluate(() => {
    window.open('http://www.example.com', '_blank');
});

该页面在browser.pages()回复中无法使用。

谢谢!

3 个答案:

答案 0 :(得分:3)

当应用程序打开新标签页时,如果没有了解您的条件,那就太难了。它对我来说非常好。这是一个代码,演示了如何使用它。阅读评论以了解相关步骤。

<强>更新:

window.open()不会返回承诺,因此browser.pages()的执行速度比浏览器创建和报告事件的速度快。我们可以使用targetcreated事件来了解是否创建了任何新标签。

browser.on('targetcreated', function(){
    console.log('New Tab Created');
})

如果您等待一段时间或退回承诺,您会看到它在browser.pages()次内报告。

await tabOne.evaluate(() => {
    window.open('http://www.example.com', '_blank');
  });
await tabOne.waitFor(2000); // await for a while
console.log("current page count ", (await browser.pages()).length); // 3

这是最终的代码。

const puppeteer = require('puppeteer');

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

  browser.on('targetcreated', function(){
    console.log('New Tab Created');
  })

  // get current tab count
  console.log("current page count ", (await browser.pages()).length); // 3

  // create a new tab
  await browser.newPage();
  // lets see if tab increased
  console.log("current page count ", (await browser.pages()).length); // 3

  // use destructuring for easier usage
  const [tabOne, tabTwo] = (await browser.pages());

  // use the tabs aka Page objects properly
  await tabOne.goto('https://example.com');
  console.log("Tab One Title ",await tabOne.title()); // Example Domain

  // use the tabs aka Page objects properly
  await tabTwo.goto('https://example.com');
  console.log("Tab Two Title ",await tabTwo.title()); // Example Domain

  await tabOne.evaluate(() => {
    window.open('http://www.example.com', '_blank');
  });
  await tabOne.waitFor(2000); // wait for a while
  console.log("current page count ", (await browser.pages()).length); // 3

  // close the browser
  await browser.close();
})();

如果你运行它,你将按以下顺序得到结果。

/*
current page count  1
New Tab Created
current page count  2
Tab One Title  Example Domain
Tab Two Title  Example Domain
New Tab Created
current page count  3
*/

答案 1 :(得分:3)

如果通过单击原始页面中的链接打开了此代码,则该代码将在新标签页中捕获新页面。

//save target of original page to know that this was the opener:     
const pageTarget = page.target();
//execute click on first tab that triggers opening of new tab:
await page.click('#selector');
//check that the first page opened this new page:
const newTarget = await browser.waitForTarget(target => target.opener() === pageTarget);
//get the new page object:
const newPage = await newTarget.page();

答案 2 :(得分:0)

this (perfectly fine!) approach 的替代方法是承诺浏览器的 "targetcreated" 事件,如对 Puppeteer issue #386 的评论中所述:

const puppeteer = require("puppeteer");
const { once } = require('events');

(async () => {
  const html = `<a href="https://news.ycombinator.com" target="_blank">click</a>`;
  const browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages(); 
  await page.setContent(html);
  await page.waitForSelector("a", {visible: true});
  console.log((await browser.pages()).length); // => 1

  const newPagePromise = once("targetcreated", browser).then(x => x.page());
  await page.click("a");
  const newPage = await newPagePromise;

  console.log((await browser.pages()).length); // => 2
  console.log((await newPage.content()));
  await browser.close();
})();

另一种写法是使用 Promise.all 和一个解构赋值来从结果数组中获取第一个元素:

const [newPage] = await Promise.all([
  once(browser, "targetcreated").then(x => x.page),
  page.click("a")
]);