Puppeteer: How to handle multiple tabs?

后端 未结 8 796
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-13 09:09

Scenario: Web form for developer app registration with two part workflow.

Page 1: Fill out developer app details and click on button to create Application ID, which

相关标签:
8条回答
  • 2020-12-13 09:29

    A new patch has been committed two days ago and now you can use browser.pages() to access all Pages in current browser. Works fine, tried myself yesterday :)

    Edit:

    An example how to get a JSON value of a new page opened as 'target: _blank' link.

    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
    
    0 讨论(0)
  • 2020-12-13 09:33

    You could remove the need to switch page in case it is caused by target="_blank" attribute - by setting target="_self"

    Example:

    element = page.$(selector)
    
    await page.evaluateHandle((el) => {
            el.target = '_self';
     }, element)
    
    element.click()
    
    0 讨论(0)
  • 2020-12-13 09:39

    If your click action is emitting a pageload, then any subsequent scripts being ran are effectively lost. To get around this you need to trigger the action (a click in this case) but not await for it. Instead, wait for the pageload:

    page.click('.get-appId');
    await page.waitForNavigation();
    

    This will allow your script to effectively wait for the next pageload event before proceeding with further actions.

    0 讨论(0)
  • 2020-12-13 09:52

    This will work for you in the latest alpha branch:

    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
    

    Be sure to use the last puppeteer version (from Github master branch) by setting package.json dependency to

    "dependencies": {
        "puppeteer": "git://github.com/GoogleChrome/puppeteer"
    },
    

    Source: JoelEinbinder @ https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315

    0 讨论(0)
  • 2020-12-13 09:52

    According to the Official Documentation:

    browser.pages()

    • returns: <Promise<Array<Page>>> Promise which resolves to an array of all open pages. Non visible pages, such as "background_page", will not be listed here. You can find them using target.page().

    An array of all pages inside the Browser. In case of multiple browser contexts, the method will return an array with all the pages in all browser contexts.

    Example Usage:

    let pages = await browser.pages();
    await pages[0].evaluate(() => { /* ... */ });
    await pages[1].evaluate(() => { /* ... */ });
    await pages[2].evaluate(() => { /* ... */ });
    
    0 讨论(0)
  • 2020-12-13 09:52

    You can't currently - Follow https://github.com/GoogleChrome/puppeteer/issues/386 to know when the ability is added to puppeteer (hopefully soon)

    0 讨论(0)
提交回复
热议问题