2014-06-10 9 views
9

Sto usando PhantomJS per accedere a un sito e fare qualcosa. Il sito ha utilizzato OAuth per l'accesso. Facendo clic sul pulsante "Accedi", accedi al servizio OAuth. Lì si inseriscono le credenziali e facendo clic su "Invia", si viene reindirizzati al sito originale. Il mio script funziona bene ma fa affidamento su timeout che non sembrano troppo robusti.Come posso aspettare che la pagina sia pronta in PhantomJS?

Come posso riscrivere il codice in modo che invece di utilizzare setTimeout, posso aspettare fino a quando la pagina è pronta. Spesso vedo errori che la pagina non è pronta e quindi jQuery non è inizializzato.

Non sono troppo bravo con Javascript, quindi un esempio sarebbe utile. Questo è quello che ho hackerato insieme dopo una tonnellata di Google. Qui è il mio codice:

var page = require('webpage').create(); 
var system = require('system'); 

page.settings.resourceTimeout = 10000; 
page.onResourceTimeout = function(e) { 
    console.log("Timed out loading resource " + e.url); 
}; 

page.open('https://mysite.com/login', function(status) { 
    if (status !== 'success') { 
     console.log('Error opening url'); 
     phantom.exit(1); 
    } else { 
     setTimeout(function() { 
      console.log('Successfully loaded page'); 
      page.evaluate(function() { 
       $("#submit-field").click(); //Clicking the login button 
      }); 

      console.log('Clicked login with OAuth button'); 
      setTimeout(function() { 
       console.log('Addding the credentials'); 
       page.evaluate(function() {     
        document.getElementById("username").value = '[email protected]'; 
        document.getElementById("password").value = '[email protected]'; 
        document.getElementById("Login").click(); 
       }); 
       console.log('Clicked login button'); 

       setTimeout(function() { 
        //Inject some jQuery into the page and invoke that here 
        console.log('Clicked the export button'); 
       }, 15000); 
      }, 15000); 
     }); 
    } 
}); 
+2

Ti suggerisco di iniziare allontanandoti dalla montagna di sventura – fmsf

+2

Dopo aver lavorato con questo per le ultime due settimane, ora so cosa intendevi con questa "montagna di sventura". È l'inferno del callback. –

risposta

14

Sembra che l'unico modo per farlo era quello di utilizzare le richiamate dal DOM a PhantomJS.

var page = require('webpage').create(); 
var system = require('system'); 

page.onInitialized = function() { 
    page.onCallback = function(data) { 
     console.log('Main page is loaded and ready'); 
     //Do whatever here 
    }; 

    page.evaluate(function() { 
     document.addEventListener('DOMContentLoaded', function() { 
      window.callPhantom(); 
     }, false); 
     console.log("Added listener to wait for page ready"); 
    }); 

}; 

page.open('https://www.google.com', function(status) {}); 
+0

webpage.create() non è un errore di funzione di ottenere –

+0

@HemantNagarkoti Assicurarsi di installare pagina Web come modulo nodo attraverso NPM. 'npm installa la pagina web --save' – matt

1

Un metodo alternativo sarebbe quello di estendere le phantomjs waitfor.js example.

Io uso questa miscela personnal di metodo. Questo è il mio main.js di file:

'use strict'; 

var wasSuccessful = phantom.injectJs('./lib/waitFor.js'); 
var page = require('webpage').create(); 

page.open('http://foo.com', function(status) { 
    if (status === 'success') { 
    page.includeJs('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', function() { 
     waitFor(function() { 
     return page.evaluate(function() { 
      if ('complete' === document.readyState) { 
      return true; 
      } 

      return false; 
     }); 
     }, function() { 
     var fooText = page.evaluate(function() { 
      return $('#foo').text(); 
     }); 

     phantom.exit(); 
     }); 
    }); 
    } else { 
    console.log('error'); 
    phantom.exit(1); 
    } 
}); 

e il file lib/waitFor.js (che è solo un copia e incolla della funzione waifFor() dalle phantomjs waitfor.js example):

function waitFor(testFx, onReady, timeOutMillis) { 
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s 
     start = new Date().getTime(), 
     condition = false, 
     interval = setInterval(function() { 
      if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { 
       // If not time-out yet and condition not yet fulfilled 
       condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code 
      } else { 
       if(!condition) { 
        // If condition still not fulfilled (timeout but condition is 'false') 
        console.log("'waitFor()' timeout"); 
        phantom.exit(1); 
       } else { 
        // Condition fulfilled (timeout and/or condition is 'true') 
        // console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); 
        typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condi> 
        clearInterval(interval); //< Stop this interval 
       } 
      } 
     }, 250); //< repeat check every 250ms 
} 

Questo metodo non è asincrona, ma a Almeno sono sicuro che tutte le risorse sono state caricate prima di provare a usarle.

Problemi correlati