面對頁面包含大量固定格式下載鏈接(ed2k、磁力鏈、迅雷專用鏈等)需求,手工複製極其低效。本文展示如何用 PHP 結合字符串查找/正則表達式,從頁面源碼中**高精度、高性能**批量提取目標鏈接,並輸出至文件供下載工具導入。
目標鏈接在 HTML 中通常有固定特徵:
<a href="ed2k://|file|...、magnet:?xt=urn:btih:...">、'>、空格、<算法流程:
file_get_contents / cURL)。<?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";
}
?>
stripos/strpos): **速度極快**,記憶體佔用低,適合**明確、固定、無嵌套**的標記(如本文場景)。preg_match_all): 功能強,能處理複雜變化模式,**但大文本下極其消耗 CPU/內存,易觸發 backtrack limit 導致失敗或極慢**。本場景不推薦作為主力。file_get_contents 獲取的是原始字節。若標記含中文或特殊字符,**必須確保 PHP 腳本編碼、標記字符串編碼、頁面實際編碼一致**,或使用 mb_convert_encoding($content, 'UTF-8', 'auto') 統一轉 UTF-8 後再處理。file_get_contents 可能佔用過多內存。可用 fopen + fread 分塊流式處理,但實現邊界匹配較複雜(需維護跨塊緩衝區)。<div class="download-list">),可先用字符串/正則提取該區塊 HTML,再在小字符串中匹配,大幅提速。User-Agent、Referer、Cookie(cURL 選項)。sleep(1~3),避免觸發頻率限制。提取的鏈接文件可直接導入:
aria2c -i links.txt 或發送 JSON-RPC aria2.addUri。PHP 批量提取固定格式鏈接,**字符串定位截取(stripos + substr)是性能與穩定性的最佳平衡點**。關鍵在於:準確定義起止標記、處理編碼、去重、異常兜底、大文件分塊策略。配合 cURL 獲取、Aria2 下載,即可構建「頁面解析 → 鏈接提取 → 高速下載」全自動流水線,徹底告別手工複製粘貼。