142 votes

phantomjs n'attend pas le chargement complet de la page

J'utilise PhantomJS v1.4.1 pour charger certaines pages web. Je n'ai pas accès à leur serveur, je reçois juste des liens pointant vers eux. J'utilise une version obsolète de Phantom car j'ai besoin de supporter Adobe Flash sur ces pages web.

Le problème est que de nombreux sites web chargent leur contenu mineur de manière asynchrone et c'est pourquoi le rappel onLoadFinished de Phantom (analogue à onLoad en HTML) se déclenche trop tôt alors que tout n'est pas encore chargé. Quelqu'un peut-il me suggérer comment attendre le chargement complet d'une page web pour faire, par exemple, une capture d'écran avec tout le contenu dynamique comme les publicités ?

3voto

Daishi Points 3730

J'utilise un mélange personnel de phantomjs waitfor.js exemple .

Il s'agit de mon main.js fichier :

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

Et le lib/waitFor.js (qui n'est qu'un copier-coller du fichier waifFor() de la fonction phantomjs waitfor.js exemple )

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
}

Cette méthode n'est pas asynchrone, mais elle me permet au moins de m'assurer que toutes les ressources ont été chargées avant que je n'essaie de les utiliser.

2voto

fdnieves Points 41

C'est une vieille question, mais comme je cherchais un chargement complet de la page pour Spookyjs (qui utilise casperjs et phantomjs) et que je n'ai pas trouvé ma solution, j'ai fait mon propre script pour cela, avec la même approche que l'utilisateur deemstone . Ce que cette approche fait, c'est que pour une quantité de temps donnée, si la page n'a pas reçu ou démarré de requête, elle terminera l'exécution.

Dans le fichier casper.js (si vous l'avez installé globalement, le chemin serait quelque chose comme /usr/local/lib/node_modules/casperjs/modules/casper.js), ajoutez les lignes suivantes :

Au début du fichier avec toutes les variables globales :

var waitResponseInterval = 500
var reqResInterval = null
var reqResFinished = false
var resetTimeout = function() {}

Ensuite, dans la fonction "createPage(casper)", juste après "var page = require('webpage').create() ;", ajoutez le code suivant :

 resetTimeout = function() {
     if(reqResInterval)
         clearTimeout(reqResInterval)

     reqResInterval = setTimeout(function(){
         reqResFinished = true
         page.onLoadFinished("success")
     },waitResponseInterval)
 }
 resetTimeout()

Puis à l'intérieur de "page.onResourceReceived = function onResourceReceived(resource) {" sur la première ligne ajouter :

 resetTimeout()

Faites de même pour "page.onResourceRequested = function onResourceRequested(requestData, request) {"

Enfin, sur "page.onLoadFinished = function onLoadFinished(status) {", à la première ligne, ajoutez :

 if(!reqResFinished)
 {
      return
 }
 reqResFinished = false

Et c'est tout, j'espère que cela aidera quelqu'un en difficulté comme je l'étais. Cette solution est pour casperjs mais fonctionne directement pour Spooky.

Bonne chance !

0voto

Tom Points 1

Voici ma solution, elle a fonctionné pour moi.

page.onConsoleMessage = function(msg, lineNum, sourceId) {

    if(msg=='hey lets take screenshot')
    {
        window.setInterval(function(){      
            try
            {               
                 var sta= page.evaluateJavaScript("function(){ return jQuery.active;}");                     
                 if(sta == 0)
                 {      
                    window.setTimeout(function(){
                        page.render('test.png');
                        clearInterval();
                        phantom.exit();
                    },1000);
                 }
            }
            catch(error)
            {
                console.log(error);
                phantom.exit(1);
            }
       },1000);
    }       
};

page.open(address, function (status) {      
    if (status !== "success") {
        console.log('Unable to load url');
        phantom.exit();
    } else { 
       page.setContent(page.content.replace('</body>','<script>window.onload = function(){console.log(\'hey lets take screenshot\');}</script></body>'), address);
    }
});

0voto

Alan P Points 41

Le déplacement de la souris pendant le chargement de la page devrait fonctionner.

 page.sendEvent('click',200, 660);

do { phantom.page.sendEvent('mousemove'); } while (page.loading);

MISE À JOUR

Lors de la soumission du formulaire, rien n'a été renvoyé et le programme s'est donc arrêté. Le programme n'a pas attendu le chargement de la page, car il a fallu quelques secondes pour que la redirection commence.

En lui demandant de déplacer la souris jusqu'à ce que l'URL passe à la page d'accueil, le navigateur disposait d'autant de temps qu'il en avait besoin pour changer. En lui demandant ensuite d'attendre que la page ait fini de se charger, on permettait à la page de se charger complètement avant que le contenu ne soit saisi.

page.evaluate(function () {
document.getElementsByClassName('btn btn-primary btn-block')[0].click();
});
do { phantom.page.sendEvent('mousemove'); } while (page.evaluate(function()
{
return document.location != "https://www.bestwaywholesale.co.uk/";
}));
do { phantom.page.sendEvent('mousemove'); } while (page.loading);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X