Screenshots von Webseiten erstellen mit PHP
Einen einfachen manuellen Screenshot von einer Webseite zu erstellen ist einfach, brauche ich hier wohl nicht extra erläutern. Wenn man allerdings aus seiner PHP-Applikation Screenshots von Webseiten erstellen möchte oder keine Lust hat auf manuelles Zusammenkopieren weil die Webseite sehr lang oder breit ist, hilft das Projekt wkhtmltopdf. Dieses Kommandozeilentool gibt es für Windows, Linux und Mac, und es läuft auch auf Servern ohne grafische Oberfläche. Auf der Webseite des Projekts findet man sowohl wkhtmltopdf als auch wkhtmltoimage. wk steht dabei für die Webkit Render Engine, die aus einem gegebenen HTML-Input entweder ein PDF oder ein Bild (jpg, png, tiff) erstellt.
Ich werde hier zeigen wie man Bilder erstellt, die Installation ist einfach: Man lädt sich die passende Version herunter, in meinem Fall für einen Debian-Server ist das wkhtmltoimage-0.10.0_rc2-static-i386.tar.bz2 . Die darin enthaltene Datei kopiere ich nach /usr/local/bin , falls bei euch open_basedir aktiv ist muss es natürlich irgendwo in ein erlaubtes Verzeichnis.
wget http://wkhtmltopdf.googlecode.com/files/wkhtmltoimage-0.10.0_rc2-static-i386.tar.bz2 tar -xjvf wkhtmltoimage-0.10.0_rc2-static-i386.tar.bz2 mv wkhtmltoimage-i386 /usr/local/bin/Ein erster kleiner Test von der Konsole:
wkhtmltoimage-i386 https://www.phpgangsta.de phpgangsta.de.jpgHier das Ergebnis (klicken für das Original Bild):
Gar nicht schlecht! Schauen wir uns als nächstes den Aufruf aus PHP heraus an.
<? passthru('/usr/local/bin/wkhtmltoimage-i386 https://www.phpgangsta.de phpgangsta.de.jpg');So einfach kann es sein! Natürlich möchte man dies variabel machen, sodass man von jeder beliebigen Webseite Screenshots erstellen kann, und auch das Format oder die Qualität wählen kann. Bei der Arbeit mit Aufrufen wie passthru() oder auch shell_exec(), exec() etc. sollte man immer aufpassen dass man die übergebenen Parameter gut prüft und entschärft (escapeshellcmd und escapeshellarg)
Auf dieser Webseite kann die Funktionalität übrigens getestet werden:
http://screenshot.phpgangsta.de
Ich habe auf GitHub die Klasse WebsiteToImage angelegt mit der die Screenshoterstellung gekapselt und vereinfacht wird. Ich freue mich natürlich über weitere implementierte Features und Pull Requests!
Aktuell sieht die Klasse so aus:
https://github.com/PHPGangsta/WebsiteToImage/blob/master/WebsiteToImage.phpUnd so wird sie benutzt:
https://github.com/PHPGangsta/WebsiteToImage/blob/master/Example.phpwkhtmltoimage hat viele interessante Funktionalitäten, beispielsweise kann man nur einen bestimmten Bereich ausschneiden, die Höhe und die Breite einstellen, die Qualität und das Format ändern. Aber es geht noch sehr viel mehr wie man unten sieht, man kann Javascript deaktivieren, Bilder auf der Webseite nicht laden, ein HTTP Authentifizierungspasswort angeben falls benötigt, einen Proxy einstellen, einen Zoomfaktor wählen und vieles mehr.
Hier die „erweiterte Hilfe“:
wkhtmltoimage-i386 -H Name: wkhtmltoimage 0.10.0 rc2 Synopsis: wkhtmltoimage [OPTIONS]... <input file> <output file> Description: Converts an HTML page into an image, General Options: --allow <path> Allow the file or files from the specified folder to be loaded (repeatable) --checkbox-checked-svg <path> Use this SVG file when rendering checked checkboxes --checkbox-svg <path> Use this SVG file when rendering unchecked checkboxes --cookie <name> <value> Set an additional cookie (repeatable) --cookie-jar <path> Read and write cookies from and to the supplied cookie jar file --crop-h <int> Set height for croping --crop-w <int> Set width for croping --crop-x <int> Set x coordinate for croping --crop-y <int> Set y coordinate for croping --custom-header <name> <value> Set an additional HTTP header (repeatable) --custom-header-propagation Add HTTP headers specified by --custom-header for each resource request. --no-custom-header-propagation Do not add HTTP headers specified by --custom-header for each resource request. --debug-javascript Show javascript debugging output --no-debug-javascript Do not show javascript debugging output (default) --encoding <encoding> Set the default text encoding, for input -H, --extended-help Display more extensive help, detailing less common command switches -f, --format <format> Output file format (default is jpg) --height <int> Set screen height (default is calculated from page content) (default 0) -h, --help Display help --htmldoc Output program html help --images Do load or print images (default) --no-images Do not load or print images -n, --disable-javascript Do not allow web pages to run javascript --enable-javascript Do allow web pages to run javascript (default) --javascript-delay <msec> Wait some milliseconds for javascript finish (default 200) --load-error-handling <handler> Specify how to handle pages that fail to load: abort, ignore or skip (default abort) --disable-local-file-access Do not allowed conversion of a local file to read in other local files, unless explecitily allowed with --allow --enable-local-file-access Allowed conversion of a local file to read in other local files. (default) --manpage Output program man page --minimum-font-size <int> Minimum font size --password <password> HTTP Authentication password --disable-plugins Disable installed plugins (default) --enable-plugins Enable installed plugins (plugins will likely not work) --post <name> <value> Add an additional post field (repeatable) --post-file <name> <path> Post an additional file (repeatable) -p, --proxy <proxy> Use a proxy --quality <int> Output image quality (between 0 and 100) (default 94) --radiobutton-checked-svg <path> Use this SVG file when rendering checked radiobuttons --radiobutton-svg <path> Use this SVG file when rendering unchecked radiobuttons --readme Output program readme --run-script <js> Run this additional javascript after the page is done loading (repeatable) -0, --disable-smart-width Use the specified width even if it is not large enough for the content --stop-slow-scripts Stop slow running javascripts (default) --no-stop-slow-scripts Do not Stop slow running javascripts (default) --transparent Make the background transparent in pngs --use-xserver Use the X server (some plugins and other stuff might not work without X11) --user-style-sheet <url> Specify a user style sheet, to load with every page --username <username> HTTP Authentication username -V, --version Output version information an exit --width <int> Set screen width (default is 1024) (default 1024) --window-status <windowStatus> Wait until window.status is equal to this string before rendering page --zoom <float> Use this zoom factor (default 1)Es gibt auch das PHP-Binding Projekt php-wkhtmltox für die C-Bibliothek libwkhtmltox, sodass man es als PHP-Extension nutzen kann (extension=phpwkhtmltox.so).
Tolles Script! Muss ich auch mal ausprobieren.
Ein kleines Manko hat es aber. Wenn auf der Homepage ein Javascript onLoad z.B. ein Menü aufklappt, wird dieses nicht vollständig angezeigt.
Ein Timeout nach onLoad von ca. 1 Sekunde wäre noch ganz praktisch…
rniederer
21 Jul 11 at 08:29
Ich bin begesitert. Super tool!
So etwas habe ich schon länger gesucht.
Lockhead
21 Jul 11 at 08:50
Ich dachte es geht um PHP und nicht um ein Script für die Shell – da passt der Titel nicht so recht 🙂
Aber trotzdem sieht das sehr interessant aus, danke für den Artikel!
Dennis Becker
21 Jul 11 at 09:05
NACHTRAG:
Warum gehst du denn nicht gleich auf die PHP Extension ein? Auf http://code.google.com/p/wkhtmltopdf/ (ganz unten) sind die PHP Bindings verlinkt auf https://github.com/mreiferson/php-wkhtmltox
Dann passt der Titel auch wieder und man muss kein Shell-Script über PHP aufrufen 😉
Dennis Becker
21 Jul 11 at 09:07
wkhtmltoimage ist ja sehr interessant! Was noch erwähnenstwert ist: das Teil macht auch von Flash Screenshots. Das war ja sonst immer sehr schmerzhaft. Super Lösung!
Nur der Vollständigkeit halber: wer den Prozess stärker scripten will (rniederer’s 1 Sekunden Delay), sollte einen Blick auf phantomjs werfen:
http://code.google.com/p/phantomjs/
Steffen
21 Jul 11 at 10:34
@Dennis: Steht in meinem Artikel auch drin (ganz unten). Habe die Extension noch nicht getestet (habe sie auch erst gefunden als ich die andere Lösung schon fertig hatte 🙂 ), deshalb noch nichts genaueres drüber geschrieben.
Michael Kliewe
21 Jul 11 at 12:18
Extrem spannend! Hab noch ein paar Probleme wkhtmltoimage ans Laufen zu kriegen, aber das wird schon. Danke für den Tipp!
BTW: Unter welcher Lizenz steht die Klasse?
Adrian
21 Jul 11 at 12:28
Das PHP Binding ist natürlich spaßig. Bisher nutze ich für sowas http://cutycapt.sourceforge.net/ bzw. einen vollwertigen Firefox oder Chromium auf der Konsole. Das ist z. B. dann praktisch, wenn man die Werbung nicht mitknipsen will. 😉
Oliver
21 Jul 11 at 12:36
Das Programm gibt mir keinen Screenshot von
http://de.wikipedia.org/wiki/Wikipedia:Irrenhaus
Naja man kann nicht alles haben 🙂
Quu
21 Jul 11 at 13:42
Sehr schön! Habe auch lange Zeit cutycapt benutzt, aber das hier sieht besser aus.
kostaki
21 Jul 11 at 14:04
Das ist super. Habe gerade wieder angefangen nach einer passenden Lösung zu suchen, um mir ein wenig Arbeit zu ersparen. Das kommt mir da wie gelegen.
maXus
22 Jul 11 at 11:42
@Adrian: MIT, BSD, GPL, such dir was aus. Darfst sie gern benutzen und verbessern, wäre super wenn du meinen Namen mit reinschreibst falls du sie weiterverbreitest.
Michael Kliewe
22 Jul 11 at 22:38
Für den Firefox gibt es eine sehr nette Extension. Nennt sich „Fireshot“ und erlaubt einen Screenshot auch von der gesamten Seite (nicht nur der sichtbare Bereich).
Stephan Schulze
25 Jul 11 at 15:21
[…] […]
Screenshot - XHTMLforum
27 Jul 11 at 15:04
Ich kriege das irgendwie nicht zum laufnen. er Führt das PHP script nicht aus. Einen Scrennshot habe ich bereits über die Console erstellen können.
chris
28 Jul 11 at 17:21
@chris
Mehr Input! Fehlermeldung? PHP Version?
Oliver
28 Jul 11 at 21:05
PHP Version 5.3.2
Ich versuche es über erstmal über ein lokale Serverumgebung (MAMP).
Ich habe deinen Quelltext so übernommen und nur den Pfad der Dateien geändert.
Fehlermeldungen habe ich leider keine. Die wkhtmltoimage Datei liegt im gleichen Ordner wie meine PHP-Dateien.
chris
29 Jul 11 at 12:34
Und dann nochmal 🙂
Oliver
29 Jul 11 at 12:56
http://christopher-boehm.de/test/
So sieht es bei mir aus. Vielleicht siehst du den Fehler
chris
29 Jul 11 at 13:12
@chris: Du hast die OSX static Variante von wkhtmltoimage genommen? Hat die Datei Ausführungsrechte für den Webserver? (755 oä?)
Hat dein Webserver Schreibrechte in dem Ordner?
Ansonsten erhöhe doch bitte dein error_reporting und schau in dein error_log. Oder alternativ auch display_errors aktivieren (siehe oben).
Michael Kliewe
29 Jul 11 at 13:15
Probier mal „./wkhtmltoimage“ statt nur „wkhtmltoimage“
Ohne Pfadangabe sucht er überall aber nicht in dem Verzeichnis.
Oliver
29 Jul 11 at 13:29
Ich habe is OSX Variante ja.
Hat die Datei Ausführungsrechte für den Webserver? (755 oä?)
– Ja
Hat dein Webserver Schreibrechte in dem Ordner?
– ja
Ansonsten erhöhe doch bitte dein error_reporting und schau in dein error_log
– Keine Fehlermeldungen
chris
29 Jul 11 at 14:18
Pfad angepasst?
Oliver
29 Jul 11 at 14:21
ja habe ich auch gemacht
chris
29 Jul 11 at 14:22
Danke für diesen Tipp! Ist ein äußert praktisches Tool.
Peter
3 Aug 11 at 11:07
Hallo,
ist der „Output File“ Pfad relativ zu dem „wkhtmltoimage“ Script oder zu dem ausführenden PHP Script?
Rob
24 Sep 11 at 05:25
@Rob: Er müßte eigentlich relativ zur wkhtmltoimage executable sein…
Michael Kliewe
25 Sep 11 at 15:34
Danke – läuft schon 1a!
Auf einem 64bit System wird die Linux Static Binary (amd64) benötigt.
Rob
25 Sep 11 at 15:50
was ist dieses attribut -i386 ? ohne gehts.. mit nicht auf windows
Suisse
1 Feb 12 at 20:05
Hallo,
ich versuche das ganze per Crontab zu realisieren. Dabei habe ich eine Erfolgsquote von 67%, d. h. bei 4 von 12 Seiten funktioniert es leider nicht. Es kommen folgende Fehlermeldungen:
QPixmap: Cannot create a QPixmap when no GUI is being used (die kommt mehrfach, was aber nichts auszumachen scheint, denn diese Meldung kommt auch bei den Seiten, bei denen es funktioniert) und
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::(verschiedene): Painter not active (erscheint insgesamt 6mal.
Ich habe keine Ahnung, woran das liegen könnte, ihr vielleicht…?
Pac-Man/Holger
26 Feb 12 at 13:37
@Pac-Man
http://code.google.com/p/wkhtmltopdf/issues/detail?id=730
Da steht was dazu. 🙂
Oliver
26 Feb 12 at 14:10
@Oliver:
Vielen Dank! *freu* Ein downgrade von wkhtmltoimage 0.11.rc1 zu 0.10.0_rc2 hat es tatsächlich gebracht… 🙂
Pac-Man/Holger
26 Feb 12 at 15:38
./wkhtmltoimage-i386: error while loading shared libraries: libXrender.so.1: cannot open shared object file: No such file or directory
Ich habe die Datei auf mein Suse 10 Linux gezogen.
Leider bekomme ich diese Fehlermeldung.
Die geforderte(n) Datei(en) sind eigentlich vorhanden.
Mache ich hier irgend etwas falsch?
lrwxrwxrwx 1 root root 19 May 3 2010 libXrender.so.1 -> libXrender.so.1.3.0
-rwxr-xr-x 1 root root 39528 Dec 3 2008 libXrender.so.1.3.0
Swiper
23 Mrz 12 at 00:09
Hallo,
ich weiß nicht ob es an meinem Server liegt jedenfalls ging bei mir dieser Befehl nicht (Timeout):
passthru(‚/usr/local/bin/wkhtmltoimage-i386 https://www.phpgangsta.de phpgangsta.de.jpg‘);
nach langer Suche und Testen, musste ich die URL in einfachen Anführungszeichen setzen also so:
passthru(„/usr/local/bin/wkhtmltoimage-i386 ‚https://www.phpgangsta.de‘ phpgangsta.de.jpg“);
Falls jemand dasselbe Problem haben sollte.
Pete
5 Sep 12 at 14:30
hi gangsta,
erstmal danke fuer die klasse klasse und die erlaeuterungen.
nach zahllosen versuchen mit wkhtmltopdf bin ich nun auf wkhtmltoimage umgestiegen, die eindeutig smoothere loesung.
dabei kam mir die kleine klasse gerade recht.
an dieser stelle moechte ich dann noch etwas senf hinzugeben:
wkhtmltoimage gibt seinen consolen-output auf stderr aus. das heisst das falls fehler auftreten diese nicht im php errorlog verfuegbar sind.
ein moeglicher workaround hierfuer waere:
(in ->start())
$return=““;
//execute command
exec($command.“ 2>&1″, $commandoutput,$returnvalue);//redirect stderr to stdout
//some errorhandling
if ($returnvalue) {
foreach($commandoutput as $cmdoutline)
{
return.= $cmdoutline.““;
}
}
return $return;
sprich dem command noch ein 2>&1 hintendranhaengen, das leitet die ausgabe auf stderr auf stdout um.
vizzy
18 Sep 12 at 14:08
Habe alles nach obiger Anweisung installiert, bekomme auf der Console immer die folgende Fehlermeldung, wenn ich aufrufe:
t565:/usr/local/bin # wkhtmltoimage-i386 http://www.seite.de http://www.seite.de.jpg
Fehlermeldung:
error while loading shared libraries: libXrender.so.1: cannot open shared object file: No such file or directory
Was ist da zu tun?
gert
26 Okt 12 at 17:06
@Swipper, habe das gleiche Problem wie Du, siehe vorigen Kommentar. Hast du inzwischen die Lösung für das Problem? Wäre net, wenn du mal posten könntest.
LG
gert
26 Okt 12 at 19:46
[…] mit was du den screenshot erzeugts? litmus? Ich benutze wkhtmltoimage. Guckst du hier: Screenshots von Webseiten erstellen mit PHP | PHP Gangsta – Der PHP Blog mit Praxisbezug Zitat von flod Achja, was fehlt ist ein Passwort zurücksetzen funktion 😉 Ich weiß, […]
sitebench.de performance monitoring - Zend Framework Forum - ZF1 / ZF2
31 Okt 12 at 10:15
[…] […]
tschibo navigation scroll - XHTMLforum
29 Nov 12 at 12:07
Hi ,habe nun das ganze System gut am laufen ,würde mich nur über eine grössenangabe freuen.
Sodass man die seiten praktisch in verschiedenen grössen bekommen kann ,das muss ich aber anders realisieren oder geht das im script ?
Webby
27 Dez 12 at 20:35
Hallo in die Runde…ein Frage von einem Rookie…kann ich das Script auch auf einem 1&1 FTP-Server verwenden und automatisieren? Ich möchte von einem öffentlichen Webcamsstream (live) regelmäßig Screenshots machen und in einem Verzeichnis auf meinem FTP-Server immer unter dem selben Namen speichern. Besten Dank schonmal…
LuckyDuke
20 Feb 17 at 11:13