场景:开发人员应用注册的Web表单,包含两部分工作流程。
第1页:填写开发者应用详细信息并单击按钮以在新标签页中创建应用程序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();
})();
更新2017-10-25
仍在寻找一个好的用法示例。
答案 0 :(得分: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
请务必将 package.json 依赖项设置为
,以使用最后一个puppeteer版本(来自Github master分支)"dependencies": {
"puppeteer": "git://github.com/GoogleChrome/puppeteer"
},
资料来源:JoelEinbinder @ https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315
答案 1 :(得分:6)
两天前提交了一个新补丁,现在您可以使用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
答案 2 :(得分:3)
browser.pages()
- 返回:
<
Promise
<
Array
<
Page
>>>
Promise解析为所有打开页面的数组。不可见的页面,例如"background_page"
,将不在此处列出。您可以使用target.page()
找到它们。浏览器中所有页面的数组。如果存在多个浏览器上下文,则该方法将返回一个数组,其中包含所有浏览器上下文中的所有页面。
用法示例:
let pages = await browser.pages();
await pages[0].evaluate(() => { /* ... */ });
await pages[1].evaluate(() => { /* ... */ });
await pages[2].evaluate(() => { /* ... */ });
答案 3 :(得分:2)
理论上,您可以覆盖window.open
功能以始终打开&#34;新标签&#34;在您当前的页面上并通过历史记录导航。
您的工作流程将是:
覆盖window.open
功能:
await page.evaluateOnNewDocument(() => {
window.open = (url) => {
top.location = url
}
})
转到第一页并执行一些操作:
await page.goto(PAGE1_URL)
// ... do stuff on page 1
点击按钮导航到第二页并在那里执行一些操作:
await page.click('#button_that_opens_page_2')
await page.waitForNavigation()
// ... do stuff on page 2, extract any info required on page 1
// e.g. const handle = await page.evaluate(() => { ... })
返回首页:
await page.goBack()
// or: await page.goto(PAGE1_URL)
// ... do stuff on page 1, injecting info saved from page 2
显然,这种方法有其缺点,但我发现它大大简化了多标签导航,如果你已经在多个标签上运行并行作业,这种方法尤其有用。不幸的是,目前的API并不是一件容易的事。
答案 4 :(得分:2)
您可以删除切换页面的必要性,以防由target="_blank"
属性引起 - 通过设置target="_self"
示例:
element = page.$(selector)
await page.evaluateHandle((el) => {
el.target = '_self';
}, element)
element.click()
答案 5 :(得分:1)
如果您的点击操作正在发出网页加载,那么正在运行的所有后续脚本都会丢失。要解决此问题,您需要触发操作(在本例中为单击),但不 await
。相反,请等待页面加载:
page.click('.get-appId');
await page.waitForNavigation();
这将允许您的脚本在继续进一步操作之前有效地等待下一个pageload事件。
答案 6 :(得分:0)
你目前无法 - 跟随https://github.com/GoogleChrome/puppeteer/issues/386知道何时将这种能力添加到木偶戏中(希望很快)
答案 7 :(得分:0)
it looks like there's a simple 'page.popup' event
对应于“弹出”窗口的页面 页面打开新标签或窗口时发出。
const [popup] = await Promise.all([ new Promise(resolve => page.once('popup', resolve)), page.click('a[target=_blank]'), ]); const [popup] = await Promise.all([ new Promise(resolve => page.once('popup', resolve)), page.evaluate(() => window.open('https://example.com')), ]);