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

PHP 實現文章內容外鏈自動過濾:保留站內鏈接移除外部鏈接

     編輯:PHP 綜合知識

為了 SEO 優化和安全性,CMS 系統常需自動識別並移除非本站域名的外部鏈接,保留純文本錨點。本文提供基於正則的完整實現,參考織夢 CMS 核心邏輯優化而來。

核心函數實現

/**
 * 刪除非站內鏈接,保留錨文本
 * @param string $body  文章內容
 * @param array  $allow_urls  允許的域名列表(含主域名)
 * @return string 處理後內容
 */
function replace_external_links(&$body, $allow_urls = array()) {
    // 1. 構建允許域名正則
    $host_rule = join('|', $allow_urls);
    $host_rule = preg_replace("#[\n\r]#", '', $host_rule);
    $host_rule = str_replace('.', '\\.', $host_rule);   // 轉義點號
    $host_rule = str_replace('/', '\\/', $host_rule);   // 轉義斜杠
    
    // 2. 匹配所有  標簽
    $matches = array();
    preg_match_all("#]*)>(.*)#iU", $body, $matches);
    
    if (!is_array($matches[0]) || empty($matches[0])) {
        return $body;
    }
    
    $replace_pairs = array();  // 待替換對應關係
    
    // 3. 遍歷判斷每個鏈接
    foreach ($matches[0] as $i => $full_tag) {
        $attrs = $matches[1][$i];  // href 等屬性
        $anchor_text = $matches[2][$i];  // 錨文本
        
        // 檢查 href 是否包含允許域名
        $is_allowed = false;
        if ($host_rule !== '' && preg_match('#' . $host_rule . '#i', $attrs)) {
            $is_allowed = true;
        }
        
        if (!$is_allowed) {
            // 外部鏈接:記錄 完整標簽 => 錨文本 的替換對
            $replace_pairs[$full_tag] = $anchor_text;
        }
    }
    
    // 4. 批量替換
    if (!empty($replace_pairs)) {
        $body = str_replace(array_keys($replace_pairs), array_values($replace_pairs), $body);
    }
    
    return $body;
}

使用示例

$content = '

歡迎訪問 官網 了解詳情。

參考文檔:幫助中心

合作夥伴:合作方

'; // 允許本站域名(支持多域名) $allowed = array('example.com', 'www.example.com', 'static.example.com'); $result = replace_external_links($content, $allowed); echo $result; /* 輸出:

歡迎訪問 官網 了解詳情。

參考文檔:幫助中心

合作夥伴:合作方

*/

進階增強版:支援 rel=nofollow、新窗口等屬性保留

function replace_external_links_advanced(&$body, $allow_urls = array(), $options = array()) {
    $defaults = array(
        'keep_anchor'     => true,      // 保留錨文本
        'add_nofollow'    => false,     // 外鏈加 nofollow 而非刪除
        'target_blank'    => false,     // 外鏈加 target=_blank
        'allowed_domains' => array(),   // 額外允許域名
    );
    $opts = array_merge($defaults, $options);
    
    $all_allowed = array_merge($allow_urls, $opts['allowed_domains']);
    $host_rule = join('|', array_map(function($d) {
        return str_replace(array('.', '/'), array('\\.', '\\/'), $d);
    }, $all_allowed));
    
    return preg_replace_callback(
        "#]*href\s*=\s*[\"']([^\"']+)[\"'][^>]*)>(.*?)#i",
        function($m) use ($host_rule, $opts) {
            $full_attrs = $m[1];
            $href = $m[2];
            $text = $m[3];
            
            // 判斷是否站內鏈接
            $is_internal = ($host_rule && preg_match('#' . $host_rule . '#i', $href));
            // 相對路徑視為站內
            if (!$is_internal && strpos($href, 'http') !== 0) {
                $is_internal = true;
            }
            
            if ($is_internal) {
                return $m[0];  // 保持原樣
            }
            
            // 外部鏈接處理策略
            if ($opts['keep_anchor'] && !$opts['add_nofollow']) {
                return $text;  // 純文本
            }
            
            // 保留標簽但添加屬性
            $attrs = $full_attrs;
            if ($opts['add_nofollow'] && strpos($attrs, 'nofollow') === false) {
                $attrs .= ' rel="nofollow"';
            }
            if ($opts['target_blank'] && strpos($attrs, 'target=') === false) {
                $attrs .= ' target="_blank"';
            }
            
            return "{$text}";
        },
        $body
    );
}

應用場景與配置建議

場景策略配置示例
SEO 權重控制刪除外鏈保留文本replace_external_links($content, ['mysite.com'])
用戶生成內容(UGC)外鏈加 nofollowreplace_external_links_advanced($c, [], ['add_nofollow'=>true])
安全防範外鏈新窗口+nofollow['add_nofollow'=>true, 'target_blank'=>true]
友鏈/合作伙伴白名單放行allowed_domains => ['partner.com']

性能優化提示

  1. 緩存編譯正則:靜態變量存儲編譯後的正則對象
  2. 長文本分塊處理:超大內容分段替換避免回溯超時
  3. 入庫時處理:編輯器保存時一次性處理,避免每次渲染計算
  4. 編輯器集成:CKEditor/UEditor 插件前端預攔截

更多內容安全技術:《PHP XSS 防護實戰》、《CMS 系統安全架構設計》

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