Come posso accedere a un iframe da CasperJS?

Ho una pagina web con un iframe. Mi piacerebbe accedere ai contenuti dell’iframe usando CasperJS . In particolare, ho bisogno di fare clic sui pulsanti e compilare un modulo. Come lo posso fare?

La pagina principale è main.html :

 main-a  main-b  

L’iframe è:

  iframe-c  

Il mio approccio ingenuo:

 var casper = require('casper').create({ verbose: true, logLevel: "debug" }); casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() { this.click('a#main-a'); this.click('a#main-b'); this.click('a#iframe-c'); }); casper.run(function() { this.exit(); }); 

Non funziona, ovviamente, perché il selettore a#iframe-c non è valido nel frame principale:

 [info] [phantom] Starting... [info] [phantom] Running suite: 2 steps [debug] [phantom] opening url: http://jim.sh/~jim/tmp/casper/main.html, HTTP GET [debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/main.html, type=Other, lock=true, isMainFrame=true [debug] [phantom] url changed to "http://jim.sh/~jim/tmp/casper/main.html" [debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/iframe.html, type=Other, lock=true, isMainFrame=false [debug] [phantom] Successfully injected Casper client-side utilities [info] [phantom] Step 2/2 http://jim.sh/~jim/tmp/casper/main.html (HTTP 200) [debug] [phantom] Mouse event 'click' on selector: a#main-a [info] [remote] pressed main-a [debug] [phantom] Mouse event 'click' on selector: a#main-b [info] [remote] pressed main-b [debug] [phantom] Mouse event 'click' on selector: a#iframe-c FAIL CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c # type: uncaughtError # error: "CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c" CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c /tmp:901 in mouseEvent /tmp:365 in click /tmp/test.js:9 /tmp:1103 in runStep /tmp:324 in checkStep 

C’è un modo per farlo funzionare? Un trucco che coinvolge direttamente i phantomjs andrebbe bene, ma non so cosa fare lì.

Sto usando CasperJS versione 1.0.0-RC1 e phantomjs versione 1.6.0.

Ho trascorso la perenne ricerca di questo, e ovviamente ho trovato la risposta pochi minuti dopo aver postato la domanda.

Posso usare i nuovi comandi di cambio dei frame aggiunti a phantomjs in questo commit . In particolare, le this.page.switchToChildFrame(0) e this.page.switchToParentFrame() . Sembra non documentato, e sembra anche che i metodi siano stati modificati per le prossime versioni, ma funziona:

 var casper = require('casper').create({ verbose: true, logLevel: "debug" }); casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() { this.click('a#main-a'); this.click('a#main-b'); this.page.switchToChildFrame(0); this.click('a#iframe-c'); this.page.switchToParentFrame(); }); casper.run(function() { this.exit(); }); 

Da 1.0 puoi usare withFrame

  casper.open("http://www.example.com/page.html", function() { casper.withFrame('flashHolder', function() { this.test.assertSelectorExists('#the-flash-thing', 'Should show Flash'); }); }); 

Di fatto, dovrai utilizzare la nuova funzione --web-security=no fornita da Phantomjs 1.5 per poter accedere a quegli iFrames e ai loro contenuti.

Supponiamo di avere diversi frame (frame1 e frame2) e dobbiamo accedere a diversi elementi (come fare clic o controllare se il tag div esce o meno) di quei frame.

 casper.withFrame('frame1', function() { var file = '//*[@id="profile_file"]'; casper.thenClick(x(file)); }); casper.withFrame('frame2', function() { casper.then(function () { casper.waitForSelector('#pageDIV', function pass() { console.log("pass"); }, function fail(){ console.log("fail"); } ); }); }); 

Puoi fare qualcosa del genere:

 casper.start("url here...", function() { this.withFrame(0, function() { this.evaluate(function() { document.querySelector('img#btn_start').click(); }) }) }); 

Puoi sostituire lo zero con il nome dell’iframe.