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

PHP 批量檢測百度收錄狀態:從原理到高效率實作

     編輯:PHP 相關知識

自動化 SEO 監控:PHP 實現百度收錄批量查詢

站長與 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
?>

進階版:批量併發查詢(cURL Multi)

單線程循環查詢受限於網路延遲,百條 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 自動巡檢:解析 sitemap.xml 定時全站掃描,發現未收錄頁面推送至百度站長平台 API。
  • 收錄率儀表板:將結果存入 MySQL/ClickHouse,配合 Grafana 視覺化展示各分類、時間維度的收錄趨勢。
  • 異常告警:核心頁面(首頁、產品頁、落地頁)收錄狀態變更時,發送郵件/企業微信/Slack 通知。

法律與道德提醒

⚠️ 百度《服務條款》禁止未經授權的自動化抓取。本代碼僅供技術學習與內部低頻監控使用。大規模商業用途請申請百度站長平台官方 API 或使用合規的第三方 SEO 數據服務商。

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