Puppeteer:如何处理多个标签?

nil*_*lsw 26 automated-tests node.js google-chrome-headless puppeteer

场景:用于开发人员应用注册的Web表单,包含两部分工作流程.

第1页:填写开发者应用程序详细信息,然后单击按钮以在新选项卡中创建应用程序ID,该ID将打开...

第2页:App ID页面.我需要从此页面复制App ID,然后关闭选项卡并返回到第1页并填写App ID(从第2页保存),然后提交表单.

我了解基本用法 - 如何打开第1页并单击打开第2页的按钮 - 但如何在新选项卡中打开第2页时如何处理?

例:

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch({headless: false, executablePath: '/Applications/Google Chrome.app'});
    const page = await browser.newPage();

    // go to the new bot registration page
    await page.goto('https://register.example.com/new', {waitUntil: 'networkidle'});

    // fill in the form info
    const form = await page.$('new-app-form');

    await page.focus('#input-appName');
    await page.type('App name here');

    await page.focus('#input-appDescription');
    await page.type('short description of app here');

    await page.click('.get-appId'); //opens new tab with Page 2

    // handle Page 2
    // get appID from Page 2
    // close Page 2

    // go back to Page 1
    await page.focus('#input-appId');
    await page.type(appIdSavedFromPage2);

    // submit the form
    await form.evaluate(form => form.submit());

    browser.close();
})();
Run Code Online (Sandbox Code Playgroud)

2017-10-25更新

仍在寻找一个好的用法示例.

rho*_*hon 11

这将在最新的alpha分支中为您工作:

const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
await page.click('my-link');
// handle Page 2: you can access new page DOM through newPage object
const newPage = await newPagePromise;
await newPage.waitForSelector('#appid');
const appidHandle = await page.$('#appid');
const appID = await page.evaluate(element=> element.innerHTML, appidHandle );
newPage.close()
[...]
//back to page 1 interactions
Run Code Online (Sandbox Code Playgroud)

通过将package.json依赖项设置为,确保使用最后一个puppeteer版本(来自Github master分支)

"dependencies": {
    "puppeteer": "git://github.com/GoogleChrome/puppeteer"
},
Run Code Online (Sandbox Code Playgroud)

资料来源:JoelEinbinder @ https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315


kai*_*iak 11

两天前已经提交了一个新补丁,现在您可以使用它browser.pages()来访问当前浏览器中的所有页面.工作正常,昨天尝试自己:)

编辑:

如何获取新页面的JSON值作为'target:_blank'链接打开的示例.

const page = await browser.newPage();
await page.goto(url, {waitUntil: 'load'});

// click on a 'target:_blank' link
await page.click(someATag);

// get all the currently open pages as an array
let pages = await browser.pages();

// get the last element of the array (third in my case) and do some 
// hucus-pocus to get it as JSON...
const aHandle = await pages[3].evaluateHandle(() => document.body);

const resultHandle = await pages[3].evaluateHandle(body => 
  body.innerHTML, aHandle);

// get the JSON value of the page.
let jsonValue = await resultHandle.jsonValue();

// ...do something with JSON
Run Code Online (Sandbox Code Playgroud)


Gra*_*ler 5

根据官方文件

browser.pages()

  • 返回:Promise解析为所有打开的页面的数组。不可见的页面(例如)将不在此处列出。您可以使用找到它们。<Promise<Array<Page>>>"background_page"target.page()

浏览器中所有页面的数组。在多个浏览器上下文的情况下,该方法将返回一个数组,其中包含所有浏览器上下文中的所有页面。

用法示例:

let pages = await browser.pages();
await pages[0].evaluate(() => { /* ... */ });
await pages[1].evaluate(() => { /* ... */ });
await pages[2].evaluate(() => { /* ... */ });
Run Code Online (Sandbox Code Playgroud)


Tho*_*ole 1

目前您还不能 - 请关注https://github.com/GoogleChrome/puppeteer/issues/386了解该功能何时添加到 puppeteer(希望很快)