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

PHP 批量提取網頁固定格式鏈接(如 ed2k/磁力鏈)實戰:從字符串匹配到高效解析

     編輯:PHP 綜合知識

前言

面對頁面包含大量固定格式下載鏈接(ed2k、磁力鏈、迅雷專用鏈等)需求,手工複製極其低效。本文展示如何用 PHP 結合字符串查找/正則表達式,從頁面源碼中**高精度、高性能**批量提取目標鏈接,並輸出至文件供下載工具導入。

核心思路:特徵定位 + 邊界截取

目標鏈接在 HTML 中通常有固定特徵:

  • 起始標記: 如 <a href="ed2k://|file|...、magnet:?xt=urn:btih:...
  • 結束標記: 如 ">、'>、空格、<

算法流程:

  1. 獲取頁面內容(file_get_contents / cURL)。
  2. 循環查找起始標記位置。
  3. 從起始位置向後查找最近的結束標記位置。
  4. 截取中間字符串作為鏈接。
  5. 移動搜索指針至結束位置繼續,直到找不到起始標記。
  6. 去重、寫入文件/數據庫。

進階實戰代碼:健壯、可配置、支援多特徵

<?php
/**
 * 批量提取頁面固定格式鏈接
 * @param string $sourceUrl 頁面 URL 或本地文件路徑
 * @param array $patterns 提取規則 ['name' => ['start' => '', 'end' => '', 'flags' => '']]
 * @param string $outputFile 輸出文件路徑
 * @return array ['links' => [], 'count' => 0, 'errors' => []]
 */
function extractLinks($sourceUrl, array $patterns, $outputFile = 'links.txt') {
    // 1. 獲取內容
    $content = @file_get_contents($sourceUrl);
    if ($content === false) {
        // 可嘗試 cURL 兜底
        $ch = curl_init($sourceUrl);
        curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => false]);
        $content = curl_exec($ch);
        $curlErr = curl_error($ch);
        curl_close($ch);
        if ($content === false) {
            return ['links' => [], 'count' => 0, 'errors' => ["獲取內容失敗: $curlErr"]];
        }
    }

    $allLinks = [];
    $contentLen = strlen($content);
    
    // 2. 遍歷每種提取規則
    foreach ($patterns as $name => $rule) {
        $startTag = $rule['start'];
        $endTag = $rule['end'];
        $flags = $rule['flags'] ?? ''; // 如 'i' 忽略大小寫
        
        $startLen = strlen($startTag);
        $pos = 0;
        
        while (true) {
            // 查找下一個起始標記
            $startPos = stripos($content, $startTag, $pos);
            if ($startPos === false) break; // 找不到結束
            
            $linkStart = $startPos + $startLen;
            
            // 查找結束標記
            $endPos = stripos($content, $endTag, $linkStart);
            if ($endPos === false) {
                // 沒找到結束標記,可能頁面截斷,嘗試找下一個起始標記
                $pos = $startPos + 1;
                continue;
            }
            
            // 截取鏈接
            $link = substr($content, $linkStart, $endPos - $linkStart);
            $link = trim($link); // 去除首尾空白
            
            if (!empty($link)) {
                $allLinks[$link] = true; // 鍵去重
            }
            
            // 移動指針:從結束標記後繼續搜索
            $pos = $endPos + strlen($endTag);
            
            // 安全閾值:防止死循環
            if ($pos >= $contentLen) break;
        }
    }

    $uniqueLinks = array_keys($allLinks);
    
    // 3. 寫入文件
    $writeOk = @file_put_contents($outputFile, implode("\n", $uniqueLinks) . "\n", LOCK_EX);
    if ($writeOk === false) {
        return ['links' => $uniqueLinks, 'count' => count($uniqueLinks), 'errors' => ["寫入文件 $outputFile 失敗"]];
    }

    return ['links' => $uniqueLinks, 'count' => count($uniqueLinks), 'errors' => []];
}

// === 使用示例 ===
$source = 'https://example.com/download_page.html'; // 或本地文件 './page.html'
$patterns = [
    'ed2k' => ['start' => '<a href="ed2k://', 'end' => '">'],
    'magnet' => ['start' => 'magnet:?xt=urn:btih:', 'end' => '"'], // 結束於雙引號
    'thunder' => ['start' => 'thunder://', 'end' => '"'],
];

$result = extractLinks($source, $patterns, 'extracted_links.txt');

echo "提取完成!共找到 {$result['count']} 條唯一鏈接。\n";
if ($result['errors']) {
    echo "警告/錯誤:\n - " . implode("\n - ", $result['errors']) . "\n";
}
echo "鏈接已保存至 extracted_links.txt\n";

// 顯示前 10 條預覽
foreach (array_slice($result['links'], 0, 10) as $link) {
    echo "$link\n";
}
?>

關鍵技術點深度解析

1. 字符串函數 vs 正則表達式

  • 字符串查找 (stripos/strpos): **速度極快**,記憶體佔用低,適合**明確、固定、無嵌套**的標記(如本文場景)。
  • 正則 (preg_match_all): 功能強,能處理複雜變化模式,**但大文本下極其消耗 CPU/內存,易觸發 backtrack limit 導致失敗或極慢**。本場景不推薦作為主力。

2. 編碼陷阱與處理

  • 頁面可能是 GBK、Big5 等編碼。file_get_contents 獲取的是原始字節。若標記含中文或特殊字符,**必須確保 PHP 腳本編碼、標記字符串編碼、頁面實際編碼一致**,或使用 mb_convert_encoding($content, 'UTF-8', 'auto') 統一轉 UTF-8 後再處理。
  • 鏈接本身可能包含 URL 編碼字符(%XX),提取後通常**保持原樣**,由下載工具解碼。

3. 大文件/超長內容優化

  • 分塊讀取: 若頁面超大(>10MB),file_get_contents 可能佔用過多內存。可用 fopen + fread 分塊流式處理,但實現邊界匹配較複雜(需維護跨塊緩衝區)。
  • 限制範圍: 很多鏈接集中在特定區塊(如 <div class="download-list">),可先用字符串/正則提取該區塊 HTML,再在小字符串中匹配,大幅提速。

4. 反爬蟲應對

  • 設置 User-Agent、Referer、Cookie(cURL 選項)。
  • 請求間隔 sleep(1~3),避免觸發頻率限制。
  • 遇到 JS 渲染頁面,需用 Headless Chrome (Puppeteer/PHP-WebDriver) 或分析 AJAX 接口直接請求數據源。

擴展:直接對接下載工具

提取的鏈接文件可直接導入:

  • 迅雷 / IDM / FDM / Motrix: 支持從文本文件批量導入鏈接。
  • Aria2(命令行/ RPC): aria2c -i links.txt 或發送 JSON-RPC aria2.addUri。
  • qBittorrent / Transmission: 支持批量添加磁力鏈/種子 URL。

總結

PHP 批量提取固定格式鏈接,**字符串定位截取(stripos + substr)是性能與穩定性的最佳平衡點**。關鍵在於:準確定義起止標記、處理編碼、去重、異常兜底、大文件分塊策略。配合 cURL 獲取、Aria2 下載,即可構建「頁面解析 → 鏈接提取 → 高速下載」全自動流水線,徹底告別手工複製粘貼。

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