Все началось с ...
Несколько лет назад я только начал знакомиться с web-программированием, и одним из моих первых «проектов» был каталожек сайтов. Разработка велась для себя, в целях повышения опыта. Но т.к. аналогичных сайтов тьма-тьмущая, хотелось сделать что-то особенное. Я решил, что каждый сайт в каталоге будет представлен со скриншотом. Как все это автоматизировать я не знал, потому первое время я делал все скриншоты руками и заливал их уже как готовые файлы.
Шло время, проект «покрылся пылью», времени заниматься ним не было, но примерно год назад накатила новая «волна креатива» и захотелось мне решить «задачку автоскриншотера».
Первое, что пришло на ум — это готовые сервисы по созданию скриншотов, предоставяющие API. Но, перебрав некоторые (сейчас уже названия не помню), понял, что это не для меня: возможности были довольно урезаны, иногда приходилось довольно долго ждать «очереди», иногда сайты на скринах выглядели довольно убого. А главной проблемой было то, что все это должно было работать асинхронно и из скрипта я бы не смог понять — то ли сервис отдал мне временную картинку-заглушку, то ли уже готовый скриншот сайта.
Итого, я решил сделать собственный «велосипед».
Выбор инструмента
Для начала, нужно было найти утилитку, умеющую делать скриншоты, работающую в linux из командной строки (сайт крутится у меня на ubuntu server, потому иксов нет). Мне помог коллега по работе, дав ссылку на CutyCapt.
CutyCapt — небольшая кросс-платформенная утилита (работающая из командной строки) для создания скриншота веб-страницы и сохранения в различные векторные и растровые форматы, включая SVG, PDF, PS, PNG, JPEG, TIFF, GIF, BM P(перевод оригинального описания с оф. сайта).
Чтобы не заниматься копипастом с официального сайта просто скажу, что там уже все описано: установка, зависимости, параметры запуска, пример, а также способ использования при отсутствии X-сервера (через xvfb-run).
Кодинг
Итак, с инструментом определились. Вернемся к сайту. Я видел это так: у администратора на страничке описания есть кнопка «сделать скриншот», которая через AJAX запрос вызывает скрипт, создающий картинку, выполняющий с ней нужные обработки (ресайз/кроп/эскиз) и др.
Сказано — сделано. Приведу часть кода моего PHP-скрипта (оставив самое основное):
<?PHP // тут какие-то действия по получению URL сайта, скрин которого нужно создать // будь то выборка из БД (по переданному id), или еще что-то $url = 'http://habrahabr.ru'; // "хардкод" для примера // имя временного файла для сохранения скриншота $tmpfname = tempnam('/tmp', 'catalog') . '.jpg'; // эскейпим перед вставкой в строку команды $url = escapeshellarg($url); // собираем командную строку // из параметров для CutyCapt я передавал только мин. ширину экрана, url и имя файла, куда сохранять скриншот - мне этого хватило // о "xvfb-run" я писал выше $cmd = sprintf('xvfb-run --server-args="-screen 0, 1024x768x24" /ПАПКА/C/БИНАРНИКОМ/CutyCapt --min-width=1280 --url=%s --out=\'%s\'', $url, $tmpfname); // Выполняем exec($cmd); // Проверяем, что скрин создался if (file_exists($tmpfname)) { // проверяем, что он не 0 байт (у меня иногда так случалось) if (filesize($tmpfname) > 1) { // а тут уже делаем с файлом по имени $tmpfname все, что душе угодно // делаем его копию в нужную папку, изменяем размер, обрезаем в нужных пропорциях, создаем дополнительный эскиз..... // я, например, использовал phpthumb (phpthumb.gxdlabs.com) для обработки $f = date("ymd_his", time()).".jpg"; // имя для скрина if (copy($tmpfname, IMAGES_DIR.$f)) { if (file_exists(IMAGES_DIR.$f)) { try{ $thumb = PhpThumbFactory::create(IMAGES_DIR.$f); // качество jpg $thumb->setOptions( array('jpegQuality' => 90) ); // изменение размер $thumb->resize(800); // обрезка до квадрата 800x800px $thumb->crop(0, 0, 800, 800); $thumb->save(IMAGES_DIR.$f); // эскизик $thumb->resize(200)->crop(0,0,200,150); $thumb->save(IMAGES_DIR.'t_'.$f); } catch(exception $e) { // обрабатываем исключение... } // здесь я сохранял имя скрина в БД, и др. } } } // удаляем временный файл unlink($tmpfname); } // тут я отправлял результат работы в json - инфу об удачном/неудачном создании скрина ?>
Ах да, хотел бы поделиться информацией о «подводных камнях»:
- Иногда CutyCapt очень долго скринил, но так и не доделывал свою работу;
- Иногда делал 0-байтные скрины
- Иногда вылетал с ошибкой на некоторых flash-сайтах. Пришлось пожертвовать ими и просто удалить flash-plugin из системы. Теперь просто на скринах на месте флеша — пусто, зато вылетов больше нет из-за флеша.
Литература:
Официальный сайт CutyCapt
PHP.net
P.S. Если кому кажется, что я мало написал про CutyCapt, говорите — я дополню статью (про��то мне показалось, что на оф. сайте все четко описано)
