【问题标题】:Wait for the page to load in a new tab after clicking the button单击按钮后等待页面在新选项卡中加载
【发布时间】:2021-03-10 00:32:52
【问题描述】:

我需要等到新页面加载完毕,点击按钮后新页面会在新标签页中打开。也就是说,我单击一个按钮,打开一个新页面(应该加载),然后单击另一个按钮。我有一些示例代码,但由于某种原因它不起作用:

const page = await browser.newPage(); 
await page.goto('https://twitter.com/amazon/'); 
await page.click('.css-1dbjc4n:nth-child(1) > .css-1dbjc4n > .css-1dbjc4n > .css-901oao > .css-4rbku5',{waitUntil: ['load', 'domcontentloaded', 'networkidle0', 'networkidle2']}); 
const page2 = (await browser.pages())[2]; 
await page2.click('#nav-main > .nav-fill > #nav-xshop-container > #nav-xshop > .nav-a:nth-child(2)');

【问题讨论】:

  • 请更详细地描述“它不起作用”。什么不起作用?也许试试this answerthis one
  • @ggorlen 不,在同一个选项卡中会打开一个新页面。我在新标签中有一个新页面。

标签: javascript node.js puppeteer


【解决方案1】:

如果我理解正确,问题在于检测新选项卡(“页面”)何时打开并获取与该选项卡关联的新页面对象。

至少有几种可用的技术。一种方法是承诺浏览器的"targetcreated" 事件,如here 所述:

const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages(); 
  await page.goto("https://twitter.com/amazon");
  const amzSel = `.css-1dbjc4n:nth-child(1) > .css-1dbjc4n > 
                  .css-1dbjc4n > .css-901oao > .css-4rbku5`;
  await page.waitForSelector(amzSel, {visible: true});
  console.log((await browser.pages()).length); // => 1

  // method 1
  const newPagePromise = new Promise(resolve => 
    browser.once("targetcreated", target => resolve(target.page()))
  );
  await page.click(amzSel);
  const newPage = await newPagePromise;
  // --------

  console.log((await browser.pages()).length); // => 2
  await newPage.waitForSelector("#nav-link-prime", {visible: true});
  await newPage.click("#nav-link-prime");
  const sel = "#prime-header-CTA-announce";
  await newPage.waitForSelector(sel, {visible: true});
  console.log(await newPage.$eval(sel, el => el.innerText.trim())); // => TRY PRIME
  //await browser.close();
})();

另一种方法是使用browser.waitForTarget来检查目标的opener()何时是上一页目标,如here所述:

const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages(); 
  await page.goto("https://twitter.com/amazon");
  const amzSel = `.css-1dbjc4n:nth-child(1) > .css-1dbjc4n > 
                  .css-1dbjc4n > .css-901oao > .css-4rbku5`;
  await page.waitForSelector(amzSel, {visible: true});
  console.log((await browser.pages()).length); // => 1

  // method 2
  const pageTarget = page.target();
  await page.click(amzSel);
  const newTarget = await browser.waitForTarget(target =>
    target.opener() === pageTarget
  );
  const newPage = await newTarget.page();
  // --------

  console.log((await browser.pages()).length); // => 2
  await newPage.waitForSelector("#nav-link-prime", {visible: true});
  await newPage.click("#nav-link-prime");
  const sel = "#prime-header-CTA-announce";
  await newPage.waitForSelector(sel, {visible: true});
  console.log(await newPage.$eval(sel, el => el.innerText.trim())); // => TRY PRIME
  //await browser.close();
})();

顺便说一句,我不确定这个特定的 Twitter/Amazon 示例有多么重要/重要,但 #nav-xshop > .nav-a:nth-child(2) 似乎不是一个可靠的选择器(它似乎在“Best Sellers”和"Prime")--我会使用 #nav-link-prime,因为它是一个直接的 id,如果那是你要找的。​​p>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多