Вашему внимания предлагаются 4 linux библиотеки создания скриншотов (Webscreenie, PhantomJs, PythonWebkit2Png и WkHtml), которые могут сделать запрос к сайту, получить ответ, отрендерить ответ, создать снимок сайта (скриншот, снапшот, в англоязычной литературе - screenshot). Либы позволяют использовать возможности WebKit в консоли.
Библиотеки создания скриншотов полностью работоспособны под Debian7, также я не заметил никаких проблем в установке и работе под Ubuntu.
1. Webscreenie
Установка Webscreenie:
The project url is: https://webscreenie.googlecode.com/svn/trunk
Команда запуска webscreenie:
/usr/bin/xvfb-run -f /tmp/Xauth -a /usr/bin/webscreenie --delay 1000 --size 1000x1000 --url 'http://jeka.by/' --file /tmp/snap/jeka.by/Webscreenie.png
2. PhantomJs
Установка PhantomJs (use precompiled binary):
cd /opt wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2 tar xjf phantomjs-1.9.7-linux-x86_64.tar.bz2 mv phantomjs-1.9.7-linux-x86_64 phantomjs rm phantomjs-1.9.7-linux-x86_64.tar.bz2 // На основе examples/rasterize.js делаем свой snapshot-phantom.js
phantom-snapshot.js:
var page = require('webpage').create(),
system = require('system'),
address, output, size;
if (system.args.length < 3 || system.args.length > 4) {
console.log('Usage: phantom-snapshot.js URL filename [width*height]');
phantom.exit(1);
} else {
address = system.args[1];
output = system.args[2];
page.viewportSize = { width: 600, height: 600 };
page.clipRect = {
top: 0,
left: 0,
width: 600,
height: 600
};
if (system.args.length > 3) {
size = system.args[3].split('x');
page.viewportSize = { width: size[0], height: size[1] };
page.clipRect = {
top: 0,
left: 0,
width: size[0],
height: size[1]
};
}
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
phantom.exit();
} else {
window.setTimeout(function () {
page.render(output, {format: 'png', quality: '80'});
phantom.exit();
}, 200);
}
});
}
Команда запуска PhantomJs:
/opt/phantomjs/bin/phantomjs /pathto/phantom-snapshot.js http://jeka.by/ /tmp/snap/jeka.by/PhantomJs.png 1000x1000
Python-webkit2png
Установка python-webkit2png:
apt-get install python-qt4 libqt4-webkit xvfb python-setuptools cd /opt git clone https://github.com/adamn/python-webkit2png.git python-webkit2png cd python-webkit2png python setup.py install
Команда запуска pythonWebkit:
webkit2png -x 1000 1000 --geometry=1000 1000 --output=/tmp/snap/jeka.by/PythonWebkit.png --timeout=180 http://jeka.by/
WkHtml
Установка WkHtml:
cd /opt wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.1-dev/wkhtmltox-0.12.1-c22928d_linux-wheezy-amd64.tar.xz tar -xpJf wkhtmltox-0.12.1-c22928d_linux-wheezy-amd64.tar.xz rm wkhtmltox-0.12.1-c22928d_linux-wheezy-amd64.tar.xz
Команда запуска WkHtmlToPng:
/opt/wkhtmltox-0.12.1-c22928d/bin/wkhtmltoimage --width 1000 --height 1000 --crop-w 1000 --crop-h 1000 --format png --quality 80 http://jeka.by/ /tmp/snap/jeka.by/WkHtml.png
Создать скриншот сайта на php
Ниже представлены php классы, которые создают и сохраняют скриншоты страницы. Для работоспособности нужно установить хотя бы одну из библиотек снапшотов. Все 4 библиотеки можно поставить одновременно на одну машину, никаких конфликтов в пакетах не возникает.
<?php
/*from config:
'snapshots' => array(
'width' => 1000,
'height' => 1000,
);*/
class Snapshot_Parser_Webscreenie extends Snapshot_Parser_Abstract
{
/**
* @param string $requestedUrl
* @param string $snapshotPath
*/
public function createSnapshot($requestedUrl, $snapshotPath)
{
$snapshotConfig = Core_Config::getValue('snapshots');
$command = $snapshotConfig['commandPath']
. ' --delay 1000 '
. ' --size ' . $snapshotConfig['width'] . 'x' . $snapshotConfig['height']
. ' --url ' . escapeshellarg($requestedUrl)
. ' --file ' . $snapshotPath;
$this->getLog()->write('Executing command: ' . $command);
$this->execute($command);
}
}
class Snapshot_Parser_PhantomJs extends Snapshot_Parser_Abstract
{
/**
* @param string $requestedUrl
* @param string $snapshotPath
* @throws Parser_Exception_OperationFailed
*/
public function createSnapshot($requestedUrl, $snapshotPath)
{
$phantomPath = "/opt/phantomjs/bin/phantomjs";
$snapshotJsFilePath = PROJECT_BIN_DIR . '/phantom-snapshot.js';
if (!file_exists($phantomPath)) {
throw new Parser_Exception_OperationFailed("Can not found PHANTOM JS by path $phantomPath. Install it or set correct path to library.");
}
$snapshotConfig = Core_Config::getValue('snapshots');
$cmd = "$phantomPath $snapshotJsFilePath $requestedUrl $snapshotPath {$snapshotConfig['width']}x{$snapshotConfig['height']}";
$this->getLog()->write('Executing command: ' . $cmd);
$this->execute($cmd);
}
}
class Snapshot_Parser_PythonWebkit extends Snapshot_Parser_Abstract
{
/**
* @param $requestedUrl
* @param $snapshotPath
* @throws Parser_Exception_OperationFailed
*/
public function createSnapshot($requestedUrl, $snapshotPath)
{
$webkit2PngPath = "/opt/python-webkit2png/scripts/webkit2png";
if (!file_exists($webkit2PngPath)) {
throw new Parser_Exception_OperationFailed("Can not found webkit2png by path $webkit2PngPath. Install it or set correct path to library.");
}
$snapshotConfig = Core_Config::getValue('snapshots');
$cmd = "python $webkit2PngPath"
. " -x {$snapshotConfig['width']} {$snapshotConfig['height']}"
. " --geometry={$snapshotConfig['width']} {$snapshotConfig['height']}"
. " --output=$snapshotPath"
. " --timeout=" . Wi_Snapshot_Parser_Abstract::PROCESS_TIMEOUT
. " $requestedUrl";
$this->getLog()->write('Executing command: ' . $cmd);
$this->execute($cmd);
}
}
class Snapshot_Parser_WkHtml extends Snapshot_Parser_Abstract
{
/**
* @param string $requestedUrl
* @param string $snapshotPath
* @throws Parser_Exception_OperationFailed
*/
public function createSnapshot($requestedUrl, $snapshotPath)
{
$libPath = "/opt/wkhtmltox-0.12.1-c22928d/bin/wkhtmltoimage";
if (!file_exists($libPath)) {
throw new Parser_Exception_OperationFailed("Can not found wkhtmltoimage by path $libPath. Install it or set correct path to library.");
}
$snapshotConfig = Core_Config::getValue('snapshots');
$cmd = $libPath
. " --width {$snapshotConfig['width']} --height {$snapshotConfig['height']}"
. " --crop-w {$snapshotConfig['width']} --crop-h {$snapshotConfig['height']}"
. " --format png"
. " --quality 80"
. " $requestedUrl $snapshotPath";
$this->getLog()->write('Executing command: ' . $cmd);
$this->execute($cmd);
}
}
Под спойлером скриншот сайта jeka.by 1000x1000px, сделанный с помощью webscreenie. Кликните по картинке для открытия в полный размер.

Какая же библиотека создания снапшотов лучше?
На этот вопрос нельзя ответить однозначно. Я проводил испытания, создавая снапшоты главных страниц сайтов, отвечающих с кодом 200. Webscrenie показал наиболее хорошие результаты в количестве успешных скриншотов. В то же время webscreenie наиболее медленная библиотека. Хотя в целом по скорости работы и по качеству все 4 либы практически одинаковы. Для Webscreenie качество снапшотов нельзя задать, как видно по коду, можно задать качество для PhantomJs и WkHtml. Для WkHtml качество нужно задавать обязательно (около 80 из 100), иначе размер снапшотов WkHtml значительно превышает все остальне библиотеки и составляет порядка 1-4Мб(!) для снапшота 1000x1000px, что слишком много.
Сравнительные результаты теста на виртуальной машине debian7 (выделено одно ядро, 1024Мб ОЗУ) в десять потоков библиотек Webscreenie, PhantomJs, WkHtml, PythonWebkit приведены в таблицах:
| всего доменов | 3382 | % успешности |
| Успешных Webscreenie | 3176 | 93,9% |
| Успешных PhantomJs | 3016 | 89% |
| Успешных WkHtml | 3055 | 90,3% |
| Успешных PythonWebkit | 3038 | 89,8% |
| Библиотека | Время, мс | Размер, кб |
|---|---|---|
| Webscreenie | 9914.76 | 398.94 |
| PhantomJs | 8533.03 | 510.06 |
| WkHtml | 7627.38 | 489.80 |
| PythonWebkit | 7936.42 | 376.79 |