站長與 SEO 人員常需檢查網站頁面是否被百度收錄。人工使用 site: 指令逐條查詢效率極低,本文提供一套基於 PHP cURL 的自動化解決方案,支援批量處理、併發請求、結果持久化,並解決反爬蟲、編碼、異常處理等實戰問題。
百度搜尋結果頁面中,若出現「抱歉,沒有找到」字樣,通常代表該 URL 未被收錄;反之若出現該 URL 的快照連結,則代表已收錄。我們通過模擬瀏覽器請求 https://www.baidu.com/s?wd=目標URL,分析回應內容判斷收錄狀態。
<?php
/**
* 檢查單一 URL 百度收錄狀態
* @param string $url 待檢測網址(需完整含協議頭)
* @return bool true=已收錄, false=未收錄/查詢失敗
*/
function checkBaiduIndexed(string $url): bool {
$queryUrl = 'https://www.baidu.com/s?wd=' . urlencode($url);
$ch = curl_init($queryUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
CURLOPT_SSL_VERIFYPEER => false, // 僅測試環境建議關閉,生產請配置 CA 憑證
CURLOPT_SSL_VERIFYHOST => false,
]);
$html = curl_exec($ch);
$errno = curl_errno($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($errno !== CURLE_OK || $info['http_code'] !== 200) {
error_log("百度查詢失敗: {$url} - cURL錯誤{$errno}: " . curl_strerror($errno));
return false;
}
// 簡單特徵判斷(實際需配合 DOM 解析更準確)
return !strpos($html, '抱歉,沒有找到') && strpos($html, $url) !== false;
}
// 用法
$url = 'https://www.example.com/article/123';
var_dump(checkBaiduIndexed($url)); // true/false
?>
單線程循環查詢受限於網路延遲,百條 URL 可能需數分鐘。使用 curl_multi 實現併發,可大幅縮短耗時:
<?php
/**
* 批量併發檢查百度收錄
* @param array $urls 待檢測 URL 陣列
* @param int $concurrency 併發數(建議 5-10,避免觸發反爬)
* @return array ['url' => ['indexed'=>bool, 'http_code'=>int, 'error'=>string]]
*/
function batchCheckBaiduIndexed(array $urls, int $concurrency = 5): array {
$results = [];
$mh = curl_multi_init();
$handles = [];
$queue = array_values($urls); // 重置鍵
// 初始化併發池
$addHandle = function(string $url) use ($mh, &$handles) {
$ch = curl_init('https://www.baidu.com/s?wd=' . urlencode($url));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; Baiduspider/2.0; +https://www.baidu.com/search/spider.html)', // 模擬蜘蛛或普通瀏覽器
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_PRIVATE => $url, // 綁定 URL 以便回調識別
]);
curl_multi_add_handle($mh, $ch);
$handles[(int)$ch] = $ch;
};
// 先填滿併發槽
for ($i = 0; $i < min($concurrency, count($queue)); $i++) {
$addHandle(array_shift($queue));
}
$active = null;
do {
$status = curl_multi_exec($mh, $active);
if ($status !== CURLM_OK) break;
// 處理完成的請求
while ($done = curl_multi_info_read($mh)) {
$ch = $done['handle'];
$url = curl_getinfo($ch, CURLINFO_PRIVATE);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$errno = curl_errno($ch);
$html = curl_multi_getcontent($ch);
$results[$url] = [
'indexed' => false,
'http_code' => $httpCode,
'error' => '',
];
if ($errno === CURLE_OK && $httpCode === 200) {
$results[$url]['indexed'] = !strpos($html, '抱歉,沒有找到') && strpos($html, $url) !== false;
} else {
$results[$url]['error'] = "cURL錯誤{$errno}: " . curl_strerror($errno);
}
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
unset($handles[(int)$ch]);
// 補充新請求
if (!empty($queue)) {
$addHandle(array_shift($queue));
}
}
// 等待活動事件
if ($active) curl_multi_select($mh, 0.5);
} while ($active || !empty($queue));
curl_multi_close($mh);
return $results;
}
// 使用示例
$urls = [
'https://www.example.com/page1',
'https://www.example.com/page2',
// ... 更多 URL
];
$results = batchCheckBaiduIndexed($urls, 8);
foreach ($results as $url => $info) {
echo "{$url}: " . ($info['indexed'] ? '✅ 已收錄' : '❌ 未收錄') . " (HTTP {$info['http_code']})" . PHP_EOL;
}
?>
| 問題 | 解決方案 |
|---|---|
| IP 被百度封禁/驗證碼 | 使用代理 IP 池(付費住宅代理效果最佳);降低併發頻率;隨機化 User-Agent;增加請求間隔 (sleep/random) |
| 判斷邏輯誤判 | 改用 DOMDocument 或 symfony/dom-crawler 解析 HTML,精確匹配 <div class="result"> 結構;檢測「百度快照」連結存在性 |
| 大量 URL 記憶體溢出 | 分批處理(每批 500-1000);結果即時寫入資料庫/CSV,釋放變數 |
| HTTPS 憑證驗證失敗 | 生產環境務必配置 CURLOPT_CAINFO 指向 cacert.pem,勿長期關閉驗證 |
| 編碼亂碼 | 確保 PHP 腳本、資料庫、HTTP 回應均為 UTF-8;mb_detect_encoding 自動轉碼 |
sitemap.xml 定時全站掃描,發現未收錄頁面推送至百度站長平台 API。⚠️ 百度《服務條款》禁止未經授權的自動化抓取。本代碼僅供技術學習與內部低頻監控使用。大規模商業用途請申請百度站長平台官方 API 或使用合規的第三方 SEO 數據服務商。