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

PHP 正則表達式提取網頁中所有 URL 鏈接的完整實現

     編輯:PHP 綜合知識

URL 結構分析

標準 HTTP URL 由三部分組成:

協議://服務器/路徑?查詢參數#錨點
https://www.example.com/path/page.html?id=123#section

各部分字符集規範 (RFC 3986)

  • 協議:http|https|ftp|mailto|tel 等
  • 服務器:域名/IP,可含端口、用戶信息
  • 路徑:/ 開頭,包含字母數字及 -._~!$&'()*+,;=:@%
  • 查詢:? 開頭,key=value 形式,& 分隔

正則表達式演進

版本 1:基礎匹配(僅域名+路徑)

/(http|https):\/\/([\w\-\.]+)(:\d+)?(\/[\w\/\-\.]*)?/i

版本 2:支持查詢參數

/(http|https|ftp):\/\/([\w\-\.]+)(:\d+)?(\/[\w\/\-\.\?\=\&\%]*)?/i

版本 3:生產級完整匹配(推薦)

$urlRegex = '/
    (https?|ftp):\/\/                    # 協議
    (?:[^\s\/?#]+\.)+[^\s\/?#]+          # 域名 (至少一個點)
    (?::\d+)?                            # 可選端口
    (?:[\/?#][^\s]*)?                    # 路徑/查詢/錨點
/ix';

版本 4:嚴格 RFC 3986 兼容(複雜度高)

$rfc3986 = '/
    [a-z][a-z0-9+\-.]*://                # scheme
    (?:[^@\/\s]+@)?                      # user:pass@
    (?:                                  
        \[[0-9a-f:]+\] |                 # IPv6
        [^\/\s:?#]+                      # domain/IPv4
    )
    (?::\d+)?                            # port
    (?:[/?#][^\s]*)?                     # path?query#fragment
/ix';

完整提取腳本

function extractUrls($html, $baseUrl = '') {
    $regex = '/(https?|ftp):\/\/[^\s\/?#].[^\s]*/i';
    
    preg_match_all($regex, $html, $matches);
    $urls = $matches[0] ?? [];
    
    // 去重
    $urls = array_unique($urls);
    
    // 相對轉絕對(可選)
    if ($baseUrl) {
        $parsed = parse_url($baseUrl);
        $base = $parsed['scheme'] . '://' . $parsed['host'];
        foreach ($urls as &$url) {
            if (strpos($url, '://') === false) {
                $url = $base . ($url[0] === '/' ? '' : '/') . $url;
            }
        }
    }
    
    // 解析組件
    $result = [];
    foreach ($urls as $url) {
        $parts = parse_url($url);
        $result[] = [
            'url' => $url,
            'scheme' => $parts['scheme'] ?? '',
            'host' => $parts['host'] ?? '',
            'port' => $parts['port'] ?? '',
            'path' => $parts['path'] ?? '',
            'query' => $parts['query'] ?? '',
            'fragment' => $parts['fragment'] ?? '',
        ];
    }
    
    return $result;
}

// 使用
$html = file_get_contents('https://example.com');
$links = extractUrls($html, 'https://example.com');
print_r($links);

進階:DOMDocument 解析(更可靠)

function extractUrlsDom($html, $baseUrl = '') {
    libxml_use_internal_errors(true);
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    libxml_clear_errors();
    
    $urls = [];
    foreach ($dom->getElementsByTagName('a') as $a) {
        $href = $a->getAttribute('href');
        if ($href) $urls[] = $href;
    }
    foreach ($dom->getElementsByTagName('img') as $img) {
        $src = $img->getAttribute('src');
        if ($src) $urls[] = $src;
    }
    foreach ($dom->getElementsByTagName('link') as $link) {
        $href = $link->getAttribute('href');
        if ($href) $urls[] = $href;
    }
    foreach ($dom->getElementsByTagName('script') as $script) {
        $src = $script->getAttribute('src');
        if ($src) $urls[] = $src;
    }
    
    return array_unique($urls);
}

方案對比

方案優點缺點適用場景
正則速度快、無依賴、可提取 JS/JSON 中的 URL易誤匹配、難處理複雜編碼純文本、腳本、API 響應、大規模掃描
DOMDocument語義準確、自動處理實體編碼、可獲取屬性上下文內存佔用大、嚴格模式下易報錯HTML 頁面結構化提取、需區分標簽類型
組合DOM 提取標簽屬性 + 正則提取內聯腳本/樣式代碼較多通用爬蟲、站點地圖生成

常見問題處理

  • 中文 URL:現代瀏覽器自動編碼,正則需允許 %xx 格式
  • JavaScript 動態生成:正則/DOM 均無法執行 JS,需 Puppeteer/Playwright 渲染後提取
  • Base64 編碼圖片:data:image/...;base64,... 非 HTTP URL,可選擇過濾
  • 相對路徑:配合 parse_url + 基礎 URL 拼接

總結

提取網頁 URL,**首選 DOMDocument 解析標簽屬性**,輔以正則提取內聯腳本/樣式/JSON 中的鏈接。生產級爬蟲建議:DOMDocument + 正則 + 相對轉絕對 + 去重 + 異常處理 組合方案。

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