Создание скриншотов сайтов, исходный код

Вашему внимания предлагаются 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. Кликните по картинке для открытия в полный размер.

Давний скриншот jeka.by
Скриншот сайта jeka.by webscreenie

Какая же библиотека создания снапшотов лучше?

На этот вопрос нельзя ответить однозначно. Я проводил испытания, создавая снапшоты главных страниц сайтов, отвечающих с кодом 200. Webscrenie показал наиболее хорошие результаты в количестве успешных скриншотов. В то же время webscreenie наиболее медленная библиотека. Хотя в целом по скорости работы и по качеству все 4 либы практически одинаковы. Для Webscreenie качество снапшотов нельзя задать, как видно по коду, можно задать качество для PhantomJs и WkHtml. Для WkHtml качество нужно задавать обязательно (около 80 из 100), иначе размер снапшотов WkHtml значительно превышает все остальне библиотеки и составляет порядка 1-4Мб(!) для снапшота 1000x1000px, что слишком много.

Сравнительные результаты теста на виртуальной машине debian7 (выделено одно ядро, 1024Мб ОЗУ) в десять потоков библиотек Webscreenie, PhantomJs, WkHtml, PythonWebkit приведены в таблицах:

Сравнительная характеристика успешности websc, wk, phantom, python
всего доменов 3382 % успешности
Успешных Webscreenie 3176 93,9%
Успешных PhantomJs 3016 89%
Успешных WkHtml 3055 90,3%
Успешных PythonWebkit 3038 89,8%

 

Среднее время создания и размер одного скриншота (quality=80)
Библиотека Время, мс Размер, кб
Webscreenie 9914.76 398.94
PhantomJs 8533.03 510.06
WkHtml 7627.38 489.80
PythonWebkit 7936.42 376.79

 

 
 
 
 

icon Комментарии 1

 nevius 2 года назад
Наша задача была создавать через заданный интервал времени скриншот страниц. Сперва сами пытались разработать что-то на основе этого, но сложновато. В итоге перепробовали разные сторонние сервисы. Подошел больше всего https://screen-archive.ru. Можно создавать архив скриншотов сайта. Правда с платными функциями, но при небольшом количестве страниц - самое то
Ваш комментарий к статье.. (для авторизованных)

ctrl+enter

icon Вход в систему

зарегистрироваться
НОВЫЕ ПОЛЬЗОВАТЕЛИ