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

PHP 抓取 Yahoo Finance 股票報價:基於 DOM 解析的爬蟲類實現

     編輯:PHP 綜合知識

實現原理

通過 fopen 獲取 https://finance.yahoo.com/q?s=SYMBOL 頁面源碼,定位 rowspan=3 標記作為數據區塊起始,提取至 ichart.yahoo.com 圖表鏈接結束,輸出原始 HTML 片段。

核心代碼

<?php
function getYahooQuote($stockSymbol = "CCR") {
    $targetURL = "https://finance.yahoo.com/q?s=$stockSymbol&d=t";
    $fd = fopen($targetURL, "r");
    if (!$fd) return false;

    $startExtract = $stopExtract = false;
    $capturedHTML = '';

    while (!feof($fd)) {
        $buffer = fgets($fd, 4096);

        if (strstr($buffer, "rowspan=3")) {
            $startExtract = true;
        }

        if ($startExtract && !$stopExtract) {
            // 截取最後一個 ")) {
            $stopExtract = true;
            echo $capturedHTML;
            break;
        }
    }
    fclose($fd);
}

// 批量抓取示例
$symbols = ['CCR', 'IIXL', 'SAPE', 'WBVN'];
foreach ($symbols as $sym) {
    echo "$sym
"; getYahooQuote($sym); } ?>

代碼缺陷與風險

問題影響修復方案
依賴特定 HTML 結構頁面改版即失效改用官方 API(Yahoo Finance API、Alpha Vantage、Twelve Data)
無錯誤處理/重試網絡波動導致數據缺失加入超時、重試、熔斷機制
同步阻塞請求批量抓取慢、併發差使用 cURL 多句柄 / Swoole / Guzzle 異步並發
直接輸出 HTML 片段難以結構化存儲/計算解析為標準數組/JSON,入庫或緩存
無 User-Agent/Referer易被反爬封禁設置合理 Header、IP 池、驗證碼識別

現代化重構範例(Guzzle + CSS 選擇器)

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;

$client = new Client(['timeout' => 10, 'headers' => ['User-Agent' => 'Mozilla/5.0...']]);

function fetchQuote(Client $client, string $symbol): ?array {
    try {
        $resp = $client->get("https://finance.yahoo.com/quote/$symbol");
        $html = (string)$resp->getBody();
        $crawler = new Crawler($html);

        // Yahoo 現代頁面使用 data-test 屬性
        $price = $crawler->filter('[data-test="qsp-price"]')->text();
        $change = $crawler->filter('[data-test="qsp-price-change"]')->text();
        $time = $crawler->filter('[data-test="qsp-market-time"]')->text();

        return [
            'symbol' => $symbol,
            'price' => (float)str_replace(',', '', $price),
            'change' => $change,
            'time' => $time,
            'fetched_at' => date('c'),
        ];
    } catch (\Exception $e) {
        error_log("Fetch $symbol failed: " . $e->getMessage());
        return null;
    }
}

// 並發批量(需 Guzzle 7+ Promise)
$promises = [];
foreach (['AAPL', 'GOOGL', 'MSFT', 'TSLA'] as $sym) {
    $promises[$sym] = $client->getAsync("https://finance.yahoo.com/quote/$sym");
}
$results = [];
foreach ($promises as $sym => $promise) {
    $resp = $promise->wait();
    $results[$sym] = fetchQuote($client, $sym); // 簡化:實際應在 then 中解析
}
print_r($results);

合規與法律提醒

  • Yahoo Finance 服務條款 禁止未授權爬蟲商業用途。
  • 高頻抓取可能觸發 WAF 封禁 IP,嚴重者面臨法律追訴。
  • 金融數據延遲、準確性無保證,決策系統請接入持牌數據商(Refinitiv、Bloomberg、Wind 等)。

結語

本文代碼僅作爬蟲入門教學演示。生產環境金融數據獲取請務必走官方 API 或授權渠道,並建立完善的錯誤重試、監控告警、合規審計體系。

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