PHP*

Делаем скриншоты сайтов

gnomeby 26 июня 2009 в 03:44 13,2k
Бродя по просторам PHP документации случайно наткнулся на две функции: imagegrabwindow и imagegrabscreen. Они умеют делать скриншоты в Microsoft Windows.
Заинтересовало. Кончилось дело тем, что был написан скриптик генерирующий полный скриншот любого сайта.
Итак нам необходимы:


В функции imagegrabwindow дан неплохой пример по использованию.
$browser = new COM("InternetExplorer.Application");
$handle = $browser->HWND;
$browser->Visible = true;
$browser->Navigate("http://www.libgd.org");

/* Still working? */
while ($browser->Busy) {
  com_message_pump(4000);
}
$im = imagegrabwindow($handle, 0);
$browser->Quit();
imagepng($im, "iesnap.png");
imagedestroy($im);


* This source code was highlighted with Source Code Highlighter.


Но он обладает большим недостатком — какого размера открылось окошко браузера, такой мы и получим скриншот.
Дабы исправить это пришлось написать скрипт, который дополнительно делает следующие вещи:
  • Раскрывает окно браузера на весь экран в полноэкранном режиме
  • Отключает полосу состояния
  • Затирает скроллинг
  • Делает необходимое число скриншотов страницы с помощью прокрутки страницы и объединяет их

Кодяра


<?php
$browser = new COM("InternetExplorer.Application");
$browser->Visible = true;
$browser->Fullscreen = true;
$browser->StatusBar = false;

$browser->Navigate("http://www.habrahabr.ru");
while ($browser->Busy)
  com_message_pump(4000);

$handle = $browser->HWND;  
$screenWidth = $browser->Width;
$screenHeight = $browser->Height;
$documentHeight = $browser->Document->body->scrollHeight;

$scrollWidth = 20;
$scrollHeight = 20;
$testPartSize = 10*1024;

$im = imagecreatetruecolor($screenWidth - $scrollWidth, $documentHeight);
for($top = 0; $top < $documentHeight; $top += $screenHeight)
{
 $browser->Document->documentElement->scrollTop=$top;
 while ($browser->Busy)
  com_message_pump(4000);
 echo $browser->Document->documentElement->scrollTop.PHP_EOL;
 
 for($i = 0; $i < 5; $i++)
 {
  $part = imagegrabwindow($handle, 0);
  $dark = imagecolorallocate($part, 0, 0, 0);
  imagefilledrectangle($part, $screenWidth - $scrollWidth, 0, $screenWidth, $screenHeight, $dark);
  $testFile = sprintf("screenshot_%05d.png", $top);
  imagepng($part, $testFile, 9, PNG_ALL_FILTERS);
  clearstatcache();
  if(filesize($testFile) > $testPartSize)
   break;
   
  echo "Bad part, name: {$testFile}, try to generate again.".PHP_EOL;
 } 
 
 imagecopy(
  $im, $part,
  0, $top,
  0, (!$top || ($top + $screenHeight) < $documentHeight) ? 0 : $screenHeight - $scrollHeight - $documentHeight % $screenHeight,
  $screenWidth - $scrollWidth, $screenHeight);  
 imagedestroy($part);  
}
imagepng($im, "screenshot.png", 9, PNG_ALL_FILTERS);
imagedestroy($im);

$browser->Quit();

* This source code was highlighted with Source Code Highlighter.


Замечания к коду

  • Иногда по непонятным причинам делается скриншот, а там чёрный экран, дабы устранить это делается запись снятого куска в файл с затёртым скроллингом, а затем проверяется размер файла. Если файл мал, скорее всего надо переснять.
  • При желании быстро протестить, можно воспользоваться следующем командной строкой:
    php -d extension_dir=c:\php\ext\ -d extension=php_gd2.dll ie.php
    где ie.php — скрипт выше.
  • Можно из под апача запускать, но для этого надо менять настройки безопасности. В документации к этим функциям написано что делать.


А как в других браузерах


Для FireFox нашёл Embedded Mozilla раздел, к сожалению требует кодирования, но при написании полноценного сервиса получится гораздо эффективнее.
UPD: Читайте коменты, там находится много ссылок того, как это делать на других движках и в других системах.

P.S. Проверено только в виртуалке на IE7.
P.S. Сам IE ненавижу, использую FireFox.
Проголосовать:
+46
Сохранить: