Кукловод обнаруживает, когда открывается новая вкладка, и получает объект страницы

Мое веб-приложение при некоторых условиях открывает новую вкладку. Но когда я пытаюсь получить все вкладки (await browser.pages()), я возвращаю только одну, начальную страницу.

Как мне добавить объект новой страницы в свой код?

Это происходит, когда вы не создаете новую вкладку с кукловодом с await browser.newPage(), но когда вы делаете что-то вроде этого:

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

Страница не будет доступна в ответе browser.pages().


person Konstantin Bodnia    schedule 01.03.2018    source источник


Ответы (3)


Когда приложение открывает новую вкладку, это сложно без знания ваших условий. У меня он отлично работает. Вот код, демонстрирующий, как я могу его использовать. Прочтите комментарии, чтобы понять действия.

ОБНОВЛЕНО:

window.open() не возвращает обещание, поэтому browser.pages () выполняется быстрее, чем браузер может создать событие и сообщить о нем. Мы можем использовать событие targetcreated, чтобы узнать, создана ли новая вкладка.

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

Если вы немного подождете или вернете обещание, вы увидите, что он сообщает об этом в пределах browser.pages() count.

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
*/
person Md. Abu Taher    schedule 03.03.2018
comment
Это когда вы создаете вкладку из своего кода. Но в моем случае вкладка создается автоматически на странице. - person Konstantin Bodnia; 06.03.2018
comment
Взглянем. Если вы замените await browser.newPage() на это: await (await browser.pages())[0].evaluate(() => {window.open('http://www.example.com', '_blank');}); Страница не будет доступна в browser.pages() ответе. - person Konstantin Bodnia; 06.03.2018
comment
Он сообщает. Просто window.open не возвращает обещание, поэтому browser.pages () еще не знает об этом. Обновление ответа с дополнительной информацией. - person Md. Abu Taher; 06.03.2018
comment
@ Md.AbuTaher mine открывает новое окно и не входит в ваш, если вы печатаете «новая вкладка создана». Не могли бы вы увидеть: stackoverflow.com/questions/51390268/? - person ziad.ali; 18.07.2018

Этот код перехватит новую страницу на новой вкладке, если она была открыта по ссылке на исходной странице.

//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();
person Robert Hillen    schedule 03.09.2019
comment
Я рад, что этот ответ намного лучше моего. Похоже, что в более новых версиях для этой цели появился хороший API. - person Md. Abu Taher; 01.10.2020
comment
это хорошо работает. можем ли мы выбрать это в качестве официального ответа? - person Billy; 17.04.2021

Альтернативой этому (прекрасно!) Подходу является обещание события "targetcreated" браузера, как описано в комментарии к Проблема с кукловодом № 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();
})();

Другой способ написать это - _3 _ и деструктурирующее присвоение для получения первого элемента из массива результатов:

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