2013-03-04 6 views
7

Beginnen Sie einfach mit Phantom.js nach der Installation über Homebrew auf meinem Mac.Wo werden Screenshots von phantom.js gespeichert?

Ich versuche, die Beispiele aus Screenshots von Webseiten zu speichern über https://github.com/ariya/phantomjs/wiki/Quick-Start

var page = require('webpage').create(); 
page.open('http://google.com', function() { 
    page.render('google.png'); 
    phantom.exit(); 
}); 

Aber ich sehe nicht, die überall Bilder. Befinden sie sich im selben Verzeichnis wie die .js-Datei?

+0

Haben Sie Schreibrechte? – user123444555621

+0

Wie kann ich das feststellen? –

Antwort

9

Normalerweise rendert PhantomJS die Bilder im selben Verzeichnis wie das Skript, das Sie ausführen. Ja, es sollte sich im selben Verzeichnis wie die JavaScript-Datei befinden, die Sie mit PhantomJS ausführen.

EDIT

Es scheint, dass das spezielle Beispiel fehlerhaft ist. Das Problem ist, dass page.render(...); einige Zeit braucht, um die Seite zu rendern, aber Sie rufen phantom.exit() an, bevor das Rendern abgeschlossen ist. Ich konnte die erwartete Ausgabe erhalten, indem dies zu tun:

var page = require('webpage').create(); 
page.open('http://google.com', function() { 
    page.render('google.png'); 
    setTimeout(function() { phantom.exit(); }, 5000) // wait five seconds and then exit; 
}); 

Leider ist dieses nicht ideal, so konnte ich mit etwas zu entwickeln, die ein Haar besser. Ich sage ein „Haar“, weil ich im Grunde Polling bin, um zu sehen, wenn die Seite Rendering abgeschlossen ist:

var done = false; //flag that tells us if we're done rendering 

var page = require('webpage').create(); 
page.open('http://google.com', function (status) { 
    //If the page loaded successfully... 
    if(status === "success") { 
     //Render the page 
     page.render('google.png'); 
     console.log("Site rendered..."); 

     //Set the flag to true 
     done = true; 
    } 
}); 

//Start polling every 100ms to see if we are done 
var intervalId = setInterval(function() { 
    if(done) { 
     //If we are done, let's say so and exit. 
     console.log("Done."); 
     phantom.exit(); 
    } else { 
     //If we're not done we're just going to say that we're polling 
     console.log("Polling..."); 
    } 
}, 100); 

Der obige Code funktioniert, da der Rückruf wird nicht sofort ausgeführt. Der Abrufcode wird gestartet und beginnt mit der Abfrage. Wenn der Callback ausgeführt wird, überprüfen wir den Status der Seite (wir wollen nur dann rendern, wenn wir die Seite erfolgreich laden konnten). Dann rendern wir die Seite und setzen die Flagge, die unser Abrufcode prüft, an true. Also das nächste Mal, wenn der Abrufcode ausgeführt wird, ist das Flag true und so beenden wir.

Dies scheint ein Problem mit der Art und Weise zu sein, wie PhantomJS den webpage#render(...) Aufruf ausführt. Ich vermutete, dass es sich um einen nicht blockierenden Anruf handelte, aber laut Autor in this issue handelt es sich um einen blockierenden Anruf. Wenn ich eine Vermutung riskieren musste, ist der Rendervorgang möglicherweise ein blockierender Aufruf, aber der Code, der das Rendering ausführt, könnte die Daten an einen anderen Thread weiterreichen, der die Daten persistiert blockierender Anruf). Leider wird dieser Aufruf wahrscheinlich immer noch ausgeführt, wenn die Ausführung zum Hauptskript zurückkehrt und phantom.exit() ausgeführt wird, was bedeutet, dass der oben erwähnte asynchrone Code niemals eine Chance erhält, zu beenden, was er tut.

Ich konnte einen Beitrag in den PhantomJS Foren finden, die sich mit what you're describing beschäftigt. Ich kann kein Problem sehen, das eingereicht wurde, also wenn Sie möchten, können Sie weitermachen und eins veröffentlichen.

+0

Irgendeine Idee, was könnte falsch sein? –

+0

Können Sie Ihren Code posten? Dann sollten wir sehen können, was vor sich geht. –

+0

Es ist direkt kopieren-einfügen der Beispiele hier: https://github.com/ariya/phantomjs/wiki/Quick-Start –

8

Ich habe das gleiche Problem wie der Autor dieses Beitrags, und keines der Codebeispiele funktionierte für mich. Irgendwie verwirrend, dass das zweite Beispiel in der Dokumentation von Phantom.js nicht funktioniert. Mit Home Brew auf Snow Leopard installiert.

fand ich working example

var page = require("webpage").create(); 
var homePage = "http://www.google.com/"; 
page.settings.javascriptEnabled = false; 
page.settings.loadImages = false; 
page.open(homePage); 
page.onLoadFinished = function(status) { 
    var url = page.url; 
    console.log("Status: " + status); 
    console.log("Loaded: " + url); 
    page.render("google.png"); 
    phantom.exit(); 
}; 
+2

Ich würde den 'onLoadFinished' Callback * vor * Calling' open() 'setzen, nur um sicher zu sein. :) –

+1

Ich denke, es gibt immer noch ein Problem, dass der Exit vor dem fertigen Rendering passieren kann, also funktioniert das nicht für mich, aber es funktioniert, wenn ich es mit der obigen Lösung kombiniere und es in eine setTimeout-Funktion setze. Es fühlt sich an, als gäbe es 2 Probleme. 1) Warten Sie, bis die Seite vor dem Rendern geladen wurde, und 2) warten Sie, bis der Rendervorgang abgeschlossen ist, bevor Sie den Vorgang beenden. Macht das Sinn (Neuling mit Phantom)? – Ian

1

Die Ursache a ist, dass page.render() das Bild nicht bereit sein, auch während der onLoadFinished() Ereignis zu machen. Möglicherweise müssen Sie einige Sekunden warten, bevor page.render() erfolgreich ausgeführt werden kann. Die einzige zuverlässige Methode zum Rendern eines Bildes in PhantomJS ist das wiederholte Aufrufen von page.render(), bis die Methode true zurückgibt und anzeigt, dass das Bild erfolgreich gerendert wurde.

Lösung:

var page = require("webpage").create(); 
var homePage = "http://www.google.com/"; 

page.onLoadFinished = function(status) { 
    var rendered, started = Date.now(), TIMEOUT = 30 * 1000; // 30 seconds 
    while(!((rendered = page.render('google.png')) || Date.now() - started > TIMEOUT)); 
    if (!rendered) console.log("ERROR: Timed out waiting to render image.") 
    phantom.exit(); 
}; 

page.open(homePage); 
+0

Interessanterweise ist der Retun-Typ von 'render' als' {void} 'dokumentiert. Ich habe tatsächlich kein Problem mit dem Rendern gefunden. Vielleicht liegt das an einer älteren Version oder der Tatsache, dass ich unter Windows und Linux bin. –

+0

Können Sie zählen, wie oft es fehlschlägt, bevor es funktioniert? –

5

Nur eine schnelle Hilfe für Menschen, die hierher kommen, suchen das Verzeichnis, in dem PhantomJS oder CasperJS die Screenshots gespeichert werden: es im Verzeichnis scripts standardmäßig ist. Sie haben jedoch Kontrolle.

Wenn Sie steuern möchten, wo sie gespeichert sind, können Sie nur den Dateinamen ändern, etwa so:

page.render('screenshots/google.jpg'); // saves to scriptLocation/screenshots/ 
page.render('/opt/google.jpg'); // saves to /screenshots (in the root) 

Oder wenn Sie CasperJS verwenden, können Sie verwenden:

casper.capture('/opt/google.jpg', 
     undefined, 
     { // imgOptions 
      format: 'jpg', 
      quality: 25 
     }); 

Hoffnung spart jemand die Ärger!

0

Stehlen von rasterize.js example, es funktioniert zuverlässiger als die akzeptierte Antwort für mich.

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

page.open('http://localhost/TestForTest/', function (status) { 
    console.log("starting..."); 
    console.log("Status: " + status); 

    if (status === "success") { 
     window.setTimeout(function() { 
      page.render('myExample.png'); 
      phantom.exit(); 
     }, 200); 
    } else { 
     console.log("failed for some reason."); 
    } 
}); 
4

Ich bin mir nicht sicher, ob sich etwas geändert hat, aber das Beispiel auf http://phantomjs.org/screen-capture.html funktionierte gut für mich:

var page = require('webpage').create(); 
page.open('http://github.com/', function() { 
    page.render('github.png'); 
    phantom.exit(); 
}); 

I PhantomJS-2.1.1-Fenster leite.

Was mich jedoch zu diesem Thread geführt hat, war ursprünglich, dass die Image-Datei nie auf meiner Festplatte erstellt wurde, genau wie die ursprüngliche Frage. Ich dachte mir, dass es eine Art von Sicherheitsproblemen war, also loggte ich mich in eine VM ein und begann damit, alles in das gleiche Verzeichnis zu stellen. Ich habe eine Batch-Datei verwendet, um phantomjs.exe mit meiner als Parameter übergebenen .js-Datei zu starten. Mit allen Dateien im selben Verzeichnis auf meiner VM funktionierte es großartig. Durch Versuch und Irrtum fand ich, dass meine Batch-Datei im selben Verzeichnis wie meine .js-Datei sein musste. Jetzt ist alles gut auf meinem Host-Rechner.

Also zusammenfassend ... es war wahrscheinlich ein sicherheitsrelevantes Problem für mich. Keine Notwendigkeit, irgendeine Art von Timeout hinzuzufügen.

Meine Antwort auf die ursprüngliche Frage wäre, wenn Sie alles richtig eingerichtet haben, wird die Datei im selben Verzeichnis wie die .js-Datei, die phantomjs.exe läuft. Ich habe versucht, einen voll qualifizierten Pfad für die Bilddatei anzugeben, aber das schien nicht zu funktionieren.

0

Viele gute Vorschläge hier. Die eine Sache, die ich hinzufügen möchte:

Ich lief ein Phantomjs Docker-Bild, und der Standardbenutzer war "phantomjs", nicht root. Ich wurde deshalb versucht, an einen Ort zu schreiben, die ich nicht Erlaubnis hatte auf (es war der PWD auf dem Docker Host) ...

> docker run -i -t -v $(pwd):/pwd --rm wernight/phantomjs touch /pwd/foo.txt 
touch: cannot touch '/pwd/foo.txt': Permission denied 

Der Code (s) vor allem Lauf ohne Fehler, aber wenn sie haben keine Berechtigung zum Ziel zu schreiben, dann werden sie die Anfrage still ignorieren ...

So zum Beispiel unter @ vivin-Paliath Code (die aktuelle akzeptierte Antwort):

var done = false; //flag that tells us if we're done rendering 

var page = require('webpage').create(); 
page.open('http://google.com', function (status) { 
    //If the page loaded successfully... 
    if(status === "success") { 
     //Render the page 
     page.render('google.png'); 
     console.log("Site rendered..."); 

     //Set the flag to true 
     done = true; 
    } 
}); 

//Start polling every 100ms to see if we are done 
var intervalId = setInterval(function() { 
    if(done) { 
     //If we are done, let's say so and exit. 
     console.log("Done."); 
     phantom.exit(); 
    } else { 
     //If we're not done we're just going to say that we're polling 
     console.log("Polling..."); 
    } 
}, 100); 

Und Wenn Sie es als Standardbenutzer ausführen, wird Folgendes ausgegeben:

Aber keine google.png und kein Fehler.Einfach das -u root dem docker-Befehl hinzuzufügen löst das, und ich bekomme das google.png in meinem CWD.

Zur Vollständigkeit der letzte Befehl:

Andockfensters run -u root -I -t -v $ (PWD):/PWD -w/PWD --rm wernight/PhantomJS PhantomJS google.js