webentwicklung-frage-antwort-db.com.de

Puppenspieler: Wie handhabt man mehrere Registerkarten?

Szenario: Webformular für die Registrierung einer Entwickler-App mit zweiteiligem Workflow.

Seite 1: Füllen Sie die Details der Entwickler-App aus und klicken Sie auf die Schaltfläche, um die Anwendungs-ID zu erstellen, die in einem neuen Tab geöffnet wird ...

Seite 2: Die App-ID-Seite. Ich muss die App-ID von dieser Seite kopieren, dann die Registerkarte schließen und zu Seite 1 zurückkehren, die App-ID (von Seite 2 gespeichert) eingeben und das Formular abschicken.

Ich verstehe die grundlegende Verwendung - wie man Seite 1 öffnet, und klicke auf die Schaltfläche, die sich öffnet - aber wie bekomme ich einen Griff auf Seite 2, wenn sie in einem neuen Tab geöffnet wird?

Beispiel:

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();
})();

Update 2017-10-25 

Suchen Sie noch nach einem guten Anwendungsbeispiel.

19
nilsw

Dies funktioniert für Sie in der neuesten Alpha-Branche:

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

Stellen Sie sicher, dass Sie die letzte Puppenspielerversion (aus dem Github-Zweigzweig) verwenden, indem Sie package.json als Abhängigkeit festlegen 

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

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

10
rhon

Vor zwei Tagen wurde ein neuer Patch bereitgestellt. Jetzt können Sie mit browser.pages() auf alle Seiten im aktuellen Browser zugreifen. Funktioniert gut, habe es gestern selbst versucht :)

Bearbeiten:

Ein Beispiel, wie ein JSON-Wert einer neuen Seite als "target: _blank" -Link geöffnet wird.

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
5
kaiak

Nach der Offizielle Dokumentation :

browser.pages ()

  • rückgabe: <Promise<Array<Page>>> Promise, die sich zu einem Array aller geöffneten Seiten auflöst. Nicht sichtbare Seiten wie "background_page" werden hier nicht aufgelistet. Sie finden sie mit target.page() .

Ein Array aller Seiten im Browser. Bei mehreren Browserkontexten gibt die Methode in allen Browserkontexten ein Array mit allen Seiten zurück.

Verwendungsbeispiel:

let pages = await browser.pages();
await pages[0].evaluate( () => { /* ... */ } );
await pages[1].evaluate( () => { /* ... */ } );
await pages[2].evaluate( () => { /* ... */ } );
2
Grant Miller

Sie können die Notwendigkeit zum Wechseln der Seite entfernen, falls dies durch das target="_blank"-Attribut verursacht wird - indem Sie target="_self" einstellen.

Beispiel:

element = page.$(selector)

await page.evaluateHandle((el) => {
        el.target = '_self';
 }, element)

element.click()
1

Theoretisch könnten Sie die window.open-Funktion überschreiben, um immer "neue Registerkarten" auf Ihrer aktuellen Seite zu öffnen und über Verlauf zu navigieren.

Ihr Workflow wäre dann:

  1. Überschreiben Sie die window.open-Funktion:

    await page.evaluateOnNewDocument(() => {
      window.open = (url) => {
        top.location = url
      }
    })
    
  2. Gehen Sie zu Ihrer ersten Seite und führen Sie einige Aktionen aus:

    await page.goto(PAGE1_URL)
    // ... do stuff on page 1
    
  3. Navigieren Sie zu Ihrer zweiten Seite, indem Sie auf die Schaltfläche klicken, und führen Sie dort einige Aktionen aus:

    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(() => { ... })
    
  4. Rückkehr zur ersten Seite:

    await page.goBack()
    // or: await page.goto(PAGE1_URL)
    // ... do stuff on page 1, injecting info saved from page 2
    

Dieser Ansatz hat natürlich seine Nachteile, aber ich finde, dass er die Navigation auf mehreren Registerkarten drastisch vereinfacht. Dies ist besonders nützlich, wenn Sie bereits parallele Jobs auf mehreren Registerkarten ausführen. Leider macht die derzeitige API keine einfache Aufgabe.

1
krukid

Wenn Ihre Klick-Aktion eine Seite auslöst, gehen alle nachfolgenden Skripts, die ausgeführt werden, verloren. Um dies zu umgehen, müssen Sie die Aktion auslösen (in diesem Fall ein Klick), aber nicht await. Warten Sie stattdessen auf die Seite:

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

Dadurch kann Ihr Skript effektiv auf das nächste Seitenaufrufereignis warten, bevor Sie mit den weiteren Aktionen fortfahren.

0
griffith_joel

Derzeit können Sie nicht - Folgen Sie https://github.com/GoogleChrome/puppeteer/issues/386 , um zu erfahren, wann die Fähigkeit zum Puppenspieler hinzugefügt wird (hoffentlich bald)

0
Thomas Walpole