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

PHP cURL 實戰:模擬登錄攜帶 Cookie 采集目標頁面數據

     編輯:PHP 綜合知識

場景:需要登錄態才能訪問的數據采集

很多網站的核心數據(價格、庫存、用戶信息)隱藏在登錄後。直接用 file_get_contents 或 fsockopen 組裝 Header 極其繁瑣,cURL 內建 Cookie 管理、重定向跟隨、SSL 支持,是模擬登錄采集的首選利器。

一、 環境準備:確保 cURL 擴展可用

Windows (XAMPP/WAMP) 啟用步驟

  1. 複製 libeay32.dll、ssleay32.dll 到系統目錄 (C:\Windows\System32)
  2. 編輯 php.ini:
    確認 extension_dir = "ext" 路徑正確
    取消註釋 extension=php_curl.dll (PHP 7.2+ 為 extension=curl)
  3. 重啟 Apache,運行 驗證

Linux/macOS

# Ubuntu/Debian
sudo apt-get install php-curl && sudo systemctl restart php8.2-fpm

# CentOS/RHEL
sudo yum install php-curl && sudo systemctl restart php-fpm

# macOS Homebrew
brew install php@8.2 --with-curl  # 現代版本默認已含

二、 核心邏輯:兩步走策略

  1. 步驟 1:POST 登錄表單 → 獲取並保存 Cookie (Session ID)
  2. 步驟 2:攜帶 Cookie 訪問目標頁面 → 解析數據

三、 完整代碼實現 (面向對象封裝版)

<?php
/**
 * 簡易 cURL 登錄采集器
 * 支持:Cookie 文件持久化、HTTPS、自定義 Header、錯誤重試
 */
class CurlScraper {
    private $cookieJar;
    private $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36';

    public function __construct(string $cookieDir = '/tmp') {
        $this->cookieJar = $cookieDir . '/cookies_' . md5(microtime()) . '.txt';
    }

    /** 步驟 1:執行登錄 */
    public function login(string $loginUrl, array $postData, array $extraHeaders = []): bool {
        $ch = curl_init($loginUrl);
        $this->setupCommonOptions($ch);
        curl_setopt_array($ch, [
            CURLOPT_POST       => true,
            CURLOPT_POSTFIELDS => http_build_query($postData),
            CURLOPT_COOKIEJAR  => $this->cookieJar,  // 保存響應 Cookie
            CURLOPT_FOLLOWLOCATION => true,          // 跟隨 302 重定向
            CURLOPT_HTTPHEADER => array_merge([
                'Content-Type: application/x-www-form-urlencoded',
                'Referer: ' . $loginUrl
            ], $extraHeaders)
        ]);

        $response = curl_exec($ch);
        $errno    = curl_errno($ch);
        $info     = curl_getinfo($ch);
        curl_close($ch);

        if ($errno) {
            error_log("Login cURL Error [$errno]: " . curl_strerror($errno));
            return false;
        }
        // 可根據 $info['http_code'] 或響應內容判斷登錄是否成功
        return $info['http_code'] === 200;
    }

    /** 步驟 2:攜帶 Cookie 獲取目標頁面 */
    public function fetch(string $targetUrl, array $getParams = []): ?string {
        $url = $getParams ? $targetUrl . '?' . http_build_query($getParams) : $targetUrl;
        $ch = curl_init($url);
        $this->setupCommonOptions($ch);
        curl_setopt_array($ch, [
            CURLOPT_COOKIEFILE => $this->cookieJar,  // 發送已保存 Cookie
            CURLOPT_HTTPGET    => true,
        ]);

        $response = curl_exec($ch);
        $errno    = curl_errno($ch);
        curl_close($ch);

        if ($errno) {
            error_log("Fetch cURL Error [$errno]: " . curl_strerror($errno));
            return null;
        }
        return $response;
    }

    /** 通用配置:超時、SSL、User-Agent、返回傳輸 */
    private function setupCommonOptions($ch): void {
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER         => false,
            CURLOPT_NOBODY         => false,
            CURLOPT_TIMEOUT        => 30,        // 總超時 30s
            CURLOPT_CONNECTTIMEOUT => 10,        // 連接超時 10s
            CURLOPT_SSL_VERIFYPEER => false,     // 生產建議 true 並配置 CA 憑證
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT      => $this->userAgent,
            CURLOPT_ENCODING       => 'gzip,deflate', // 自動解壓
        ]);
    }

    public function __destruct() {
        if (file_exists($this->cookieJar)) @unlink($this->cookieJar);
    }
}

// ========== 使用示例 ==========
$scraper = new CurlScraper();

// 1. 登錄 (根據目標站點實際表單字段調整)
$loginOk = $scraper->login(
    'https://b2b.example.com/checkUser.jsp',
    ['user' => 'your_account', 'password' => 'your_pass']
);

if (!$loginOk) {
    die('登錄失敗,請檢查賬號/密碼/驗證碼邏輯');
}

// 2. 采集目標頁面
$html = $scraper->fetch('https://b2b.example.com/search/b2b_zxsm_new.jsp');
if ($html) {
    // 這裡接 DOM 解析 (DOMDocument/SimpleXML/QueryList 等)
    echo "采集成功,內容長度: " . strlen($html) . " bytes\n";
    // 示例:正則提取
    // preg_match_all('/<td class="price">(.*?)<\/td>/', $html, $m);
    // print_r($m[1]);
} else {
    echo "采集失敗\n";
}

四、 進階實戰技巧

1. 處理驗證碼 / CSRF Token

  • 圖形驗證碼:需接入 OCR API (百度/騰訊雲/自建 Tesseract) 識別后提交
  • CSRF Token:先 GET 登錄頁解析 <input name="_token">,再攜帶提交

2. 維持長期會話 (免頻繁登錄)

// 固定 Cookie 文件路徑,多次運行復用
$scraper = new CurlScraper('/var/www/myproject/runtime/cookies');
// 登錄成功后手動備份 Cookie 文件,下次直接實例化復用
// 甚至可導出 JSON 格式注入瀏覽器調試

3. 并發采集 (cURL Multi / Rolling Curl)

單線程采集效率低,參考 Rolling cURL 並發方案 實現多 URL 并發,配合 CURLOPT_COOKIEFILE 共享同一 Cookie 池。

4. 反反爬蟲策略

手段應對
IP 限流代理 IP 池輪換 (CURLOPT_PROXY)
User-Agent 檢測隨機真實 UA 池
Referer/Origin 校驗動態設置匹配目標域名
JS 渲染/加密參數升級為 Puppeteer/Playwright/Selenium 頭less 瀏覽器
行為分析(鼠標軌跡等)模擬人類操作間隔、隨機點擊

5. HTTPS 證書驗證最佳實踐

// 生產環境請勿關閉驗證!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, '/etc/ssl/certs/ca-certificates.crt'); // 系統 CA 憑證包路徑

五、 常見錯誤排查

  1. 返回空/亂碼:檢查 CURLOPT_ENCODING、目標站是否 gzip、編碼轉換 mb_convert_encoding
  2. Cookie 失效:打印 curl_getinfo($ch, CURLINFO_COOKIELIST) 確認 Cookie 域/路徑/過期時間
  3. 302 重定向丟失 Cookie:確保 CURLOPT_FOLLOWLOCATION = true 且同域名下 Cookie 自動攜帶
  4. cURL Error 60 (SSL 證書):更新 CA 憑證包或臨時關閉驗證 (僅測試環境)

六、 總結

cURL 模擬登錄采集的核心在于 CookieJar/CookieFile 雙文件機制 實現會話保持。封裝為可復用類,配合異常處理、日誌記錄、并發擴展,即可構建穩健的采集基礎設施。
⚠️ 法律提醒:請遵守目標站點 robots.txt、用戶協議及《網絡安全法》,僅用于合法授權數據獲取。

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