it-swarm.com.de

speichern Sie die HTML-Ausgabe der Seite nach Ausführung des Javascript der Seite

Es gibt eine Website, die ich zu kratzen versuche, die zuerst ein HTML/js lädt Ändert die Formulareingabefelder mit js und dann POSTs . Wie kann ich die endgültige HTML-Ausgabe der geposteten Seite erhalten?

Ich habe versucht, dies mit Phantomjs zu tun, aber es scheint nur eine Option zum Rendern von Bilddateien zu haben. Googeln bedeutet, dass es möglich sein sollte, aber ich kann nicht herausfinden, wie. Mein Versuch:

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

Dieser Code wird für einen Client verwendet. Ich kann nicht erwarten, dass er zu viele Pakete installiert (nodejs, casperjs usw.).

Vielen Dank

49
gyaani_guy

der ausgegebene Code ist korrekt, aber es gibt ein Problem mit der Synchronität. Die Ausgabezeilen, die Sie haben, werden ausgeführt, bevor die Seite vollständig geladen ist. Sie können in den onLoadFinished Callback einbinden, um herauszufinden, wann dies der Fall ist. Siehe vollständigen Code unten.

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

Wenn Sie eine Website wie Google verwenden, kann dies zu Täuschungen führen, da sie so schnell geladen wird, dass Sie ein Screengrab-Inline-Programm oft so ausführen können, wie Sie es haben. In phantomjs ist Timing eine knifflige Angelegenheit. Manchmal teste ich mit setTimeout, ob Timing ein Problem ist. 

26
uffa

Wenn ich Ihren Code direkt kopiert und die URL in www.google.com geändert habe, hat er mit zwei gespeicherten Dateien einwandfrei funktioniert:

  • 1.html
  • export.png

Beachten Sie, dass die Dateien an den Ort geschrieben werden, von dem aus Sie das Skript ausführen, und nicht an den Ort, an dem sich Ihre .js-Datei befindet

4
Owen Martin

Nach zwei langen Tagen des Kämpfens und der Frustration wurde mein ähnliches Problem endlich gelöst. Der Trick war das waitfor.js Beispiel in PhantomJS 'offizielle Website . Sei glücklich!

"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

Ich benutze CasperJS , um Tests mit PhantomJS auszuführen. Ich habe diesen Code meiner tearDown - Funktion hinzugefügt:

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

Siehe docs für capture und getHTML .

0
Ben Hutchison

Ich habe verschiedene Ansätze für ähnliche Aufgaben ausprobiert und die besten Ergebnisse mit Selenium erzielt.

Bevor ich PhantomJS und Cheerio ausprobiert habe. Phantom stürzte zu oft ab, als JS auf der Seite ausgeführt wurde.

0
strah