web-dev-qa-db-fra.com

enregistrer la sortie HTML de la page après l'exécution du code javascript de la page

Il existe un site que je suis en train d'essayer de gratter, qui charge d'abord un fichier html/js Modifie les champs de saisie de formulaire à l'aide de js, puis de POSTs .

J'ai essayé de faire cela avec phantomjs, mais il semble ne disposer que d'une option permettant de restituer des fichiers image. Googling autour suggère que cela devrait être possible, mais je ne peux pas comprendre comment. Ma tentative:

var page = require('webpage').create();
var fs = require('fs');
page.open('https://www.somesite.com/page.aspx', function () {
    page.evaluate(function(){

    });

    page.render('export.png');
    fs.write('1.html', page.content, 'w');
    phantom.exit();
});

Ce code sera utilisé pour un client, je ne peux pas m'attendre à ce qu'il installe trop de paquets (nodejs, casperjs, etc.)

Merci

49
gyaani_guy

le code de sortie que vous avez est correct, mais il y a un problème avec Synchronicity. Les lignes de sortie que vous avez sont en cours d’exécution avant le chargement de la page. Vous pouvez établir une liaison avec le rappel onLoadFinished pour savoir quand cela se produit. Voir le code complet ci-dessous.

    var page = new WebPage()
    var fs = require('fs');

    page.onLoadFinished = function() {
      console.log("page load finished");
      page.render('export.png');
      fs.write('1.html', page.content, 'w');
      phantom.exit();
    };

    page.open("http://www.google.com", function() {
      page.evaluate(function() {
      });
    });

Lorsque vous utilisez un site comme Google, cela peut être décevant, car le chargement est tellement rapide que vous pouvez souvent exécuter un screengrab en ligne comme vous l'avez. Le timing est une chose délicate dans phantomjs, parfois je teste avec setTimeout pour voir si le timing est un problème. 

26
uffa

Lorsque j'ai copié directement votre code et modifié l'URL en www.google.com, tout a bien fonctionné, avec deux fichiers enregistrés:

  • 1.html
  • export.png

Gardez à l'esprit que les fichiers seront écrits à l'emplacement où vous exécutez le script et non à l'emplacement de votre fichier .js.

4
Owen Martin

Après 2 longues journées de lutte et de frustration, j'ai finalement résolu le même problème. Le truc était le waitfor.js exemple sur le site web officiel de PhantomJS . Soyez heureux!

"use strict";

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 condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 250); //< repeat check every 250ms
};


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

// Open Twitter on 'sencha' profile and, onPageLoad, do...
page.open("http://Twitter.com/#!/sencha", function (status) {
    // Check for page load success
    if (status !== "success") {
        console.log("Unable to access network");
    } else {
        // Wait for 'signin-dropdown' to be visible
        waitFor(function() {
            // Check in the page if a specific element is now visible
            return page.evaluate(function() {
                return $("#signin-dropdown").is(":visible");
            });
        }, function() {
           console.log("The sign-in dialog should be visible now.");
           phantom.exit();
        });
    }
});
2
Heitor

J'utilise CasperJS pour exécuter des tests avec PhantomJS. J'ai ajouté ce code à ma tearDown fonction:

var require = patchRequire(require);
var fs = require('fs');

casper.test.begin("My Test", {
    tearDown: function(){
        casper.capture("export.png");
        fs.write("1.html", casper.getHTML(undefined, true), 'w');
    },
    test: function(test){
        // test code

        casper.run(function(){
            test.done();
        });
    }
});

Voir docs pour capture et getHTML .

0
Ben Hutchison

J'ai essayé plusieurs approches pour une tâche similaire et les meilleurs résultats obtenus avec Selenium.

Avant j'ai essayé PhantomJS et Cheerio . Phantom plantait trop souvent lors de l'exécution de JS sur la page.

0
strah