網頁採集是 PHP 開發中常見的需求,無論是數據分析、內容聚合還是自動化測試,掌握高效且穩健的採集技巧都至關重要。本文將通過一個完整的 PHP 採集函數實例,深入解析 URL 解析、Header 偽裝、編碼處理、以及正則提取鏈接等核心環節,助你快速上手網頁採集開發。
以下封裝了一個通用的 get_url_content 函數,支援 file_get_contents 與 cURL 兩種模式,並自動處理編碼轉換與 Base 標籤注入:
<?php
function get_url_content($Url, $Method = 'c') {
global $Charset;
$Urlarr = parse_url($Url);
if (!isset($Urlarr['host'])) return false;
// 智能構建 Header,偽裝 Referer 與 Host
foreach (getallheaders() as $key => $val) {
if ($key === 'Host') $val = $Urlarr['host'];
if ($key === 'Referer') $val = 'https://' . $Urlarr['host'];
$str .= "$key: $val, ";
}
if (!preg_match('/Referer/i', $str)) $str .= "Referer: https://{$Urlarr['host']}, ";
$Header = array(trim($str));
// 選擇採集方式
if ($Method === 'f' && function_exists('file_get_contents')) {
$opts = array('http' => array('method' => 'GET', 'header' => $Header));
$cxContext = stream_context_create($opts);
$file_contents = @file_get_contents($Url, false, $cxContext);
} elseif ($Method === 'c' && function_exists('curl_init')) {
$Ch = curl_init();
$Timeout = 5;
curl_setopt($Ch, CURLOPT_HTTPHEADER, $Header);
curl_setopt($Ch, CURLOPT_URL, $Url);
curl_setopt($Ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($Ch, CURLOPT_CONNECTTIMEOUT, $Timeout);
$file_contents = curl_exec($Ch);
curl_close($Ch);
}
// 注入 base 標籤,修正相對路徑資源
$file_contents = str_replace('</title>', '</title> <base href="https://' . $Urlarr['host'] . '/" />', $file_contents);
// 自動檢測並轉換編碼
if (!preg_match('/charset=([^<>"]*)"/isU', $file_contents, $lang)) $lang[1] = 'GBK';
if (function_exists('mb_convert_encoding')) {
$target = empty($Charset) ? 'UTF-8' : $Charset;
$file_contents = mb_convert_encoding($file_contents, $target, $lang[1]);
}
return $file_contents;
}
?>
通過 getallheaders() 獲取當前請求頭,動態替換 Host 與 Referer,使目標伺服器誤以為請求來自站內,有效繞過基於 Referer 的簡易防盜鏈策略。
正則提取頁面 charset,若無則預設 GBK(中文站常見),再統一轉為 UTF-8 或指定 $Charset,解決亂碼難題。
在 </title> 後插入 <base href="...">,確保採集頁面中的相對路徑圖片、CSS、JS 能正確加載,預覽時樣式不會錯亂。
<?php
header('Content-Type: text/html; charset=UTF-8');
// 1. 採集 hao123 首頁
$file = get_url_content('https://www.hao123.com', 'f');
$file = strip_tags($file, '<a>'); // 只保留 a 標籤
// 2. 正則提取所有 http 鏈接
preg_match_all('/(http:[^"<>]*)>/isU', $file, $link);
$links = $link[1];
// 3. 選取第 11 個鏈接進行詳情採集(索引 10)
$x = 10;
$detail = get_url_content($links[$x]);
echo $detail;
?>
curl_multi 或 Swoole 協程,避免單線程阻塞。robots.txt、控制請求頻率、勿採集受版權保護內容。掌握正則表達式與 cURL 是 PHP 採集的基石。本文提供的函數已涵蓋編碼、防盜鏈、相對路徑等實戰痛點,可直接作為項目基礎組件。建議在實際專案中加入日誌、佇列、去重、入庫等模組,構建穩健的採集系統。