在 Windows 服務器環境下,PHP 可通過 COM 組件調用 Internet Explorer 實現網頁截圖。本文提供完整代碼示例:啟動 IE 實例、導航目標頁面、等待加載完成、截取窗口、生成縮略圖,並說明環境要求與局限性。
com_dotnet 擴展(php.ini: extension=com_dotnet)<?php
/**
* 截取 IE 頁面並生成縮略圖
* @param string $url 目標 URL
* @param string $outputDir 輸出目錄
* @param array $thumbSize 縮略圖尺寸 [width, height]
* @return string|false 縮略圖路徑或 false
*/
function captureIEThumbnail($url, $outputDir = 'public/images/', $thumbSize = [206, 132]) {
// 確保輸出目錄存在
if (!is_dir($outputDir)) {
mkdir($outputDir, 0755, true);
}
try {
// 1. 創建 IE 實例
$ie = new COM("InternetExplorer.Application") or die("無法創建 IE COM 組件");
$ie->Visible = true; // 必須可見才能截圖
$ie->FullScreen = true; // 全屏模式避免邊框
// 2. 導航目標頁面
$ie->Navigate2($url);
// 3. 等待加載完成
$timeout = 30; // 秒
$start = time();
while ($ie->Busy || $ie->ReadyState != 4) {
com_message_pump(1000); // 處理 COM 消息隊列
if (time() - $start > $timeout) {
throw new Exception("頁面加載超時: $url");
}
usleep(50000); // 50ms
}
// 額外等待 JS 渲染
sleep(2);
// 4. 獲取窗口句柄並截圖
$handle = $ie->HWND;
$im = imagegrabwindow($handle, 0); // 0 = 客戶區域
if (!$im) {
throw new Exception("imagegrabwindow 失敗,句柄: $handle");
}
// 5. 保存原圖(可選)
$timestamp = time();
$originalFile = $outputDir . "ie_{$timestamp}_original.png";
imagepng($im, $originalFile);
// 6. 生成縮略圖
$thumb = imagecreatetruecolor($thumbSize[0], $thumbSize[1]);
// 保持比例縮放(示例:從 1024x768 縮放)
$srcW = imagesx($im);
$srcH = imagesy($im);
imagecopyresampled($thumb, $im, 0, 0, 0, 0, $thumbSize[0], $thumbSize[1], $srcW, $srcH);
$thumbFile = $outputDir . "ie_{$timestamp}_thumb.png";
imagepng($thumb, $thumbFile);
// 7. 清理資源
imagedestroy($im);
imagedestroy($thumb);
$ie->Quit();
unset($ie);
// 強制垃圾回收 COM 物件
com_message_pump(1000);
return $thumbFile;
} catch (Exception $e) {
error_log("IE 截圖失敗: " . $e->getMessage());
if (isset($ie)) {
try { $ie->Quit(); } catch (Exception $e) {}
}
return false;
}
}
// 使用示例
$thumb = captureIEThumbnail('https://www.example.com');
if ($thumb) {
echo "縮略圖已生成: $thumb";
} else {
echo "截圖失敗";
}
com_message_pump()單線程 COM 模型需要定期泵送消息隊列,否則 IE 會凍結。在等待循環中每次調用 com_message_pump(1000) 處理 1秒 消息。
imagegrabwindow() 參數$handle:IE 窗口句柄 $ie->HWND$client_area:0=整個窗口,1=客戶區域(不含標題欄/邊框)while ($ie->Busy || $ie->ReadyState != 4) { ... }
ReadyState:0=未初始化, 1=加載中, 2=加載完成, 3=交互中, 4=完全就緒。需同時檢查 Busy 標志。
imagecopyresampled()高質量重採樣縮放,參數:目標圖像、源圖像、目標坐標、源坐標、目標寬高、源寬高。
| 問題 | 原因 | 解決 |
|---|---|---|
| Class 'COM' not found | 未啟用 com_dotnet 擴展 | php.ini 啟用 extension=com_dotnet,重啟 PHP |
| IE 啟動失敗/空白頁 | 權限不足/無桌面交互 | 配置 IIS 應用程序池身份為具體用戶、啟用「允許服務與桌面交互」 |
| 截圖為黑屏/空白 | IE 未完全渲染/硬件加速衝突 | 增加等待時間、關閉 IE 硬件加速、使用 Visible=true |
| 高併發下資源耗盡 | 每次請求啟動獨立 IE 進程 | 改用無頭瀏覽器(Puppeteer/Playwright)或隊列化處理 |
IE COM 方案存在嚴重局限:僅限 Windows、資源佔用大、併發極差、IE 已停止維護。新項目建議使用:
await page.screenshot({path: 'thumb.png'})chrome --headless --screenshot --window-size=1024,768 https://example.comPHP COM 組件調用 IE 實現網頁截圖是 Windows 歷史環境下的特有方案。代碼核心在於:COM 實例化 → 導航等待 → 句柄截圖 → GD 縮放。受限於架構缺陷,僅適用於低頻、內部、Windows 綁定場景。現代項目應遷移至無頭瀏覽器生態,獲得跨平台、高併發、標準化的截圖能力。