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

PHP 實現站內全文搜尋:從遞歸遍歷到高效索引的進化之路

     編輯:PHP 相關知識

基礎架構:搜尋表單與入口腳本

搜尋功能起始於簡單的 HTML 表單,提交關鍵字至處理腳本 search.php。首要任務是獲取並驗證輸入:

<?php
$keyword = trim($_POST['keyword'] ?? '');
if (empty($keyword)) {
    exit('關鍵字不能為空');
}
// 後續處理...
?>

核心挑戰:文件系統遞歸遍歷

早期方案採用 opendir()/readdir() 遞歸掃描目錄樹,讀取每個文件內容進行字符串匹配。核心代碼結構:

function searchFiles($dir, $keyword, &$results) {
    $handle = opendir($dir);
    while (false !== ($file = readdir($handle))) {
        if ($file === '.' || $file === '..') continue;
        $path = "$dir/$file";
        if (is_dir($path)) {
            searchFiles($path, $keyword, $results); // 遞歸進入子目錄
        } else {
            // 處理文件匹配邏輯
        }
    }
    closedir($handle);
}

關鍵優化:精準提取可搜尋內容

1. 跳過非文本文件與自身腳本

僅處理 HTML/PHP 等文本文件,排除圖片、二進制文件及搜尋腳本本身:

$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
if (!in_array($ext, ['html','htm','php','txt','xml'])) continue;
if ($file === 'search.php') continue;

2. 剝離 HTML 標籤,聚焦可見文本

使用正則提取 <body> 內容,再以 strip_tags() 移除標籤:

$content = file_get_contents($path);
if (preg_match('/<body[^>]*>(.+)<\/body>/is', $content, $m)) {
    $text = strip_tags($m[1]);
} else {
    $text = strip_tags($content);
}

3. 智能提取頁面標題

從 <title> 標籤獲取標題,作為搜尋結果展示:

$title = '無標題';
if (preg_match('/<title>(.+)<\/title>/i', $content, $m)) {
    $title = trim($m[1]);
}

4. 大小寫不敏感匹配與結果收集

使用 stripos() 或 preg_match() 進行匹配,將符合條件的文件路徑與標題存入結果數組:

if (stripos($text, $keyword) !== false) {
    $results[] = ['path' => $path, 'title' => $title];
}

進階優化:效能與體驗提升

防止腳本超時

大量文件遍歷極易觸發 max_execution_time 限制,需在腳本開頭設置:

set_time_limit(600); // 10 分鐘

結果鏈接化輸出

將結果渲染為可點擊鏈接,支援新視窗打開:

foreach ($results as $item) {
    echo "<a href='{$item['path']}' target='_blank'>{$item['title']}</a><br>";
}

編碼兼容性處理

統一轉換為 UTF-8 進行匹配,避免亂碼:

$content = mb_convert_encoding($content, 'UTF-8', 'auto');

從暴力遍歷到倒排索引:架構升級指南

上述方案僅適合中小型站點(文件數 < 5,000)。大型站點必須引入索引機制:

方案原理適用場景複雜度
文件遍歷實時掃描文件系統小型靜態站、臨時需求低
數據庫全文索引MySQL FULLTEXT / PostgreSQL tsvector動態內容管理系統(CMS)中
專用搜尋引擎Elasticsearch、Meilisearch、Algolia大規模、高併發、需分詞/同義詞/權重高
倒排索引自建定時任務構建詞→文檔映射表中型靜態站、不想引入重組件中高

輕量級倒排索引實現思路

  1. 構建階段:定時腳本遍歷文件 → 分詞(PHP 分詞庫如 Jieba、SCWS) → 建立 詞 → [文檔ID, 詞頻, 位置] 映射 → 序列化存儲(Redis/文件/SQLite)。
  2. 查詢階段:用戶關鍵字分詞 → 查找倒排鏈 → 合併評分(TF-IDF/BM25) → 排序返回 Top-K。
  3. 增量更新:文件變更時僅更新受影響詞條,避免全量重建。

安全與工程化建議

  • 輸入過濾:關鍵字長度限制、特殊字符轉義、防止正則注入(preg_quote())。
  • 資源限制:單次查詢最大掃描文件數、最大執行時間、內存上限。
  • 緩存策略:熱門關鍵字結果緩存(Redis/Memcached),減少重複計算。
  • 日誌監控:記錄查詢關鍵字、耗時、結果數、錯誤堆棧,支援性能分析與業務洞察。

站內搜尋是用戶體驗的關鍵環節。從簡單的文件遍歷起步,隨著業務增長平滑遷移至專業搜尋引擎,是架構演進的必經之路。選型時以「滿足當前業務、預留擴展空間、控制運維成本」為原則,切勿過度設計。

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