首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 產生網頁快照(縮圖)實作:呼叫第三方 API 完整範例

     編輯:PHP 相關知識

前言

PHP 本身無內建瀏覽器渲染引擎,無法直接將網頁轉為圖片。常見做法是呼叫第三方截圖服務 API(如 Urlbox、ScreenshotAPI、PageCapture 等)或自架 Headless Chrome(Puppeteer/Playwright)服務。本文以原文提供的 ppt.cc API 為例,說明整合流程、錯誤處理與現代替代方案。

原始 API 封裝函式(重構版)

<?php
/**
 * 取得網頁快照圖片網址或儲存至本地
 *
 * @param string $site   目標網址(需含 http(s)://)
 * @param string $path   本地儲存路徑,留空則只回傳圖片 URL
 * @param int    $delay  渲染延遲秒數
 * @return string|int|false  圖片 URL / 儲存位元組數 / 失敗回傳 false
 */
function snapshot(string $site, string $path = '', int $delay = 0): string|int|false
{
    // 驗證網址格式
    if (!filter_var($site, FILTER_VALIDATE_URL)) {
        trigger_error("無效網址: $site", E_USER_WARNING);
        return false;
    }

    $apiEndpoint = 'https://ppt.cc/yo2/catch.php';
    $query = http_build_query([
        'url'   => $site,
        'delay' => $delay,
        'rnd'   => mt_rand(1, 9)
    ]);

    $ch = curl_init($apiEndpoint);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $query,
        CURLOPT_USERAGENT      => $_SERVER['HTTP_USER_AGENT'] ?? 'PHP Snapshot Bot',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_FOLLOWLOCATION => true,
    ]);

    $data = curl_exec($ch);
    $err  = curl_error($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($err || $code !== 200) {
        trigger_error("API 請求失敗: $err (HTTP $code)", E_USER_WARNING);
        return false;
    }

    // API 回傳 32 字元雜湊碼
    if (strlen($data) !== 32) {
        trigger_error("API 回傳異常: $data", E_USER_WARNING);
        return false;
    }

    // 組裝圖片 URL(依 API 規則:前 3 字元為目錄層級)
    $hash = $data;
    $dir  = "{$hash[0]}/{$hash[1]}/{$hash[2]}/";
    $imageUrl = "https://cache.ppt.cc/{$dir}src_{$hash}.png";

    if ($path !== '') {
        $imgData = @file_get_contents($imageUrl);
        if ($imgData === false) {
            trigger_error("圖片下載失敗: $imageUrl", E_USER_WARNING);
            return false;
        }
        $bytes = file_put_contents($path, $imgData);
        return $bytes ?: false;
    }

    return $imageUrl;
}

// 使用範例
$url = 'https://www.baidu.com';

// 1. 只取得圖片網址
$imgUrl = snapshot($url);
echo "快照圖片: $imgUrl\n";

// 2. 直接儲存至本地
$bytes = snapshot($url, __DIR__ . '/snapshots/baidu.png');
echo $bytes ? "儲存成功 ($bytes bytes)" : "儲存失敗";

關鍵點解析

  • API 依賴性:此範例強依賴 ppt.cc 服務,若服務停止或變更規則將失效。生產環境建議自架或採用商業 SLA 服務。
  • 錯誤處理:加入 CURL 錯誤檢查、HTTP 狀態碼驗證、回傳內容長度驗證,避免靜默失敗。
  • 隨機參數:rnd 參數防止快取,確保取得最新快照。
  • 非同步優化:大量截圖時建議使用佇列(Redis + Worker)非同步處理,避免阻塞 Web 請求。

現代自架方案推薦:Headless Chrome + Puppeteer/Playwright

不依賴第三方,完全掌控渲染品質、等待邏輯、驗證碼處理等。

Node.js 微服務範例(Puppeteer)

// screenshot-service.js
const express = require('express');
const puppeteer = require('puppeteer');
const app = express();
app.use(express.json());

let browser;
puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }).then(b => browser = b);

app.post('/snapshot', async (req, res) => {
    const { url, delay = 1000, fullPage = true } = req.body;
    if (!url) return res.status(400).json({ error: 'url required' });

    const page = await browser.newPage();
    await page.setViewport({ width: 1280, height: 720 });
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
    await new Promise(r => setTimeout(r, delay));
    const buffer = await page.screenshot({ fullPage, type: 'png' });
    await page.close();

    res.set('Content-Type', 'image/png');
    res.send(buffer);
});

app.listen(3000, () => console.log('Screenshot service on :3000'));

PHP 呼叫微服務

function snapshotLocal(string $url, string $savePath = '', int $delay = 1000): string|false
{
    $ch = curl_init('https://localhost:3000/snapshot');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode(['url' => $url, 'delay' => $delay]),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 60,
    ]);
    $img = curl_exec($ch);
    if (curl_errno($ch)) return false;
    curl_close($ch);

    if ($savePath) return file_put_contents($savePath, $img) ?: false;
    return 'data:image/png;base64,' . base64_encode($img); // 或存檔後回傳 URL
}

總結

快速原型可用第三方 API;正式專案建議自架 Headless Chrome 服務,配合佇列非同步處理,兼具穩定性、彈性與成本控制。PHP 僅負責發起請求與儲存,渲染工作交給專業工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved