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

PHP 網頁快照類實作:含快取機制、相對路徑轉絕對與腳本過濾

     編輯:PHP 相關知識

前言:為何需要網頁快照?

網頁快照(Web Snapshot)技術常用於搜尋引擎索引、離線閱讀、內容備份、跨域內容代理等場景。本文介紹一個功能完整的 snap 類別,支援快取過期控制、HTML 內容清理(移除 Script)、相對 URL 自動轉絕對路徑,並提供詳細除錯日誌。

類別架構總覽

<?php
class snap {
    // 核心屬性
    private $dir;        // 快取目錄
    private $log;        // 除錯日誌
    private $contents;   // 最終輸出內容
    private $filename;   // 快取檔案路徑
    private $host;       // 目標站點基礎 URL
    private $name;       // 快取檔名(MD5)
    private $data_ts;    // 快取檔修改時間
    private $ttl;        // 快取存活秒數
    private $url;        // 目標 URL
    private $ts;         // 時間差

    public function __construct() {
        $this->log = "New snap() object instantiated.
\n"; $this->dir = dirname(__FILE__) . '/'; } // ... 核心方法詳見下文 } ?>

核心流程:fetch() 方法

public function fetch($url = '', $ttl = 10) {
    $this->log .= "--------------------------------
fetch() called
\n"; $this->log .= "url: {$url}
\n"; if (empty($url)) { $this->log .= "OOPS: You need to pass a URL!
\n"; return false; } // 解析目標主機 $hosts = parse_url($url); $this->host = $hosts['scheme'] . '://' . $hosts['host'] . '/'; $this->ttl = $ttl; $this->url = $url; $this->name = md5($this->url); $this->filename = $this->dir . $this->name; $this->log .= "Filename: {$this->filename}
\n"; $this->getFile_ts(); // 取得快取檔時間 $this->file_get_content(); // 讀取內容(快取或遠端) return true; }

智慧快取機制:file_get_content()

private function file_get_content() {
    ob_start();
    $this->ts = time() - $this->data_ts;

    // 快取存在且未過期 → 讀取本地快取
    if ($this->data_ts !== 0 && $this->ts <= $this->ttl) {
        $this->log .= "cache has expired
\n"; // 註:原碼邏輯文字與條件相反,實際為「未過期」 @readfile($this->filename); $this->contents = ob_get_contents(); ob_end_clean(); } // 快取不存在或已過期 → 抓取遠端並更新快取 else { $this->log .= "cache hasn't expired
\n"; // 同上,實際為「需更新」 @readfile($this->url); $this->contents = ob_get_contents(); ob_end_clean(); $this->saveToCache(); } return true; }

⚠️ 注意:原始碼的日誌訊息與邏輯判斷文字相反,實際執行流程正確。建議修正日誌文字避免誤導。

快取寫入與內容處理:saveToCache()

private function saveToCache() {
    $this->log .= "saveToCache() called
\n"; if (!$fp = @fopen($this->filename, 'w')) { $this->log .= "Could not open {$this->filename}
\n"; return false; } // 核心處理:相對路徑轉絕對 + 移除 Script 標籤 $this->contents = $this->formaturl($this->contents, $this->host); $this->contents = preg_replace("']*?>.*?'si", '', $this->contents); if (!@fwrite($fp, $this->contents)) { $this->log .= "Could not write to {$this->filename}
\n"; fclose($fp); return false; } fclose($fp); return true; }

相對 URL 轉絕對路徑核心演算法

formaturl() 與 lIIIIl()(建議重命名為 convertToAbsoluteUrl())協同工作:

  1. 使用複雜正則匹配所有 img[src]、link[href]、a[href] 標籤(雙引號/單引號)。
  2. 提取 URL 部分,判斷類型:
  • 已是絕對路徑(含 http/https/ftp)→ 保持不變
  • 以 / 開頭 → 網域根目錄絕對路徑
  • 以 ../ 開頭 → 相對上層目錄,遞迴處理
  • 以 ./ 開頭 → 相對當前目錄
  • mailto:、javascript: → 保持不變
  • 其他 → 視為相對當前路徑
  1. 重組完整 URL 並替換回原標籤。

使用範例:test.php

<?php
require_once dirname(__FILE__) . '/snap.class.php';
$h = new snap();
$h->fetch($_GET['url']);
// echo $h->log; // 除錯用
echo $h->contents;
?>

現代化改良建議

面向原始做法建議改良
HTTP 客戶端readfile() + 輸出緩衝Guzzle / cURL,支援標頭、逾時、重試、代理
HTML 解析正則表達式DOMDocument / Masterminds\HTML5 / Symfony DomCrawler
快取儲存本地檔案系統Redis / Memcached / 資料庫,支援分散式部署
快取策略固定 TTL支援 ETag/Last-Modified 驗證、快取標籤、主動清除
安全性無防護SSRF 防護(封鎖內網 IP)、內容型別驗證、大小限制
編碼處理假設單一編碼自動偵測 charset(mb_detect_encoding + iconv)

總結

snap 類別展示了網頁快照的核心邏輯:抓取 → 處理相對路徑 → 移除腳本 → 快取 → 輸出。雖然正則解析 HTML 有脆弱性,但對於簡單場景仍具參考價值。現代專案建議採用成熟的 HTTP 客戶端與 HTML 解析器,並建立完善的快取與安全防護機制。

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