早年在公司曾撰寫過類似的資料擷取程式,近期應前主管之託,開發了一個簡易的 Yahoo 財經股票資料抓取工具。雖然技術深度不高,但完整示範了從遠端抓取 HTML、正則解析關鍵欄位,到本地檔案快取的完整流程,適合初學者參考。
程式後續加入了簡易的資料快取功能(未使用成熟的 lite_cache,改以原生檔案操作實現),可避免頻繁請求遠端伺服器造成負擔或被封鎖。
完整程式碼如下,已加入註解說明關鍵邏輯:
<?php
set_time_limit(0); // 移除執行時間限制
$max_time = 3600; // 快取有效期:1 小時
$cache_file = 'cache_yahoo.txt';
$nowtime = time();
$filetime = file_exists($cache_file) ? filemtime($cache_file) : 0;
// 判斷快取是否過期
if ($filetime + $max_time < $nowtime) {
// 快取過期,重新抓取並更新
ob_start(); // 開啟輸出緩衝
// 定義解析函式
function get_yahoo_info($url) {
$content = file_get_contents($url);
$info = [];
// 公司名稱與代碼
$pattern = '|<tr class="yfnc_modtitle1"><td><small><b>(.*)</b> \(.*\) (.*)</small></td><td align="right">|U';
preg_match_all($pattern, $content, $out);
$info['company_name'] = $out[1][0] ?? '';
$info['company_stock'] = $out[2][0] ?? '';
// 最近交易價
$pattern = '|<td class="yfnc_tablehead1" width="52%">最近交易價:</td><td class="yfnc_tabledata1"><big><b>(.*)</b></big></td>|U';
preg_match_all($pattern, $content, $out);
$info['stock_price'] = $out[1][0] ?? '';
// 漲跌幅
$pattern = '|<td class="yfnc_tablehead1" width="52%">漲跌:</td><td class="yfnc_tabledata1">(.*)</td>|U';
preg_match_all($pattern, $content, $out);
$info['stock_upordown'] = $out[1][0] ?? '';
// 市值
$pattern = '|<td class="yfnc_tablehead1" width="54%">市值:</td><td class="yfnc_tabledata1">(.*)</td>|U';
preg_match_all($pattern, $content, $out);
$info['stock_value'] = $out[1][0] ?? '';
return $info;
}
// 從 url.txt 讀取多支股票網址(逗號分隔)
$urls = explode(',', file_get_contents('url.txt'));
$matchs = [];
$i = 0;
foreach ($urls as $url) {
$rs = get_yahoo_info(trim($url));
if (!empty($rs)) {
$matchs[$i] = $rs;
$i++;
}
}
// 輸出 HTML 表格
?>
<table border="1" width="100%" cellpadding="6" style="border-collapse: collapse" bordercolor="#8CBFF9" cellspacing="0" bgcolor="#DFEDFD">
<tr>
<td width="30" height="" valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"><div align="center">公司名稱</div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"><div align="center">股票代號</div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"><div align="center">股票價格</div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"><div align="center">股票漲幅</div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#E1EEFD"><div align="center">市值</div></td>
</tr>
<?php
$i = 1;
foreach ($matchs as $match) {
?>
<tr>
<td height="" align="center" valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><?=$i?></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><div align="center"><?=$match['company_name']?></div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><div align="center"><?=$match['company_stock']?></div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><div align="center"><?=$match['stock_price']?></div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><div align="center"><?=$match['stock_upordown']?></div></td>
<td valign="top" bordercolor="#ABD0FA" bgcolor="#FFFFFF"><div align="center"><?=$match['stock_value']?></div></td>
</tr>
<?php
$i++;
}
?>
</table>
<?php
// 寫入快取檔案(含檔案鎖定防併發)
$content = ob_get_clean();
$fp = fopen($cache_file, 'w');
if (!$fp) die('無法開啟快取檔案');
if (flock($fp, LOCK_EX)) {
if (!fwrite($fp, $content)) die('快取寫入失敗');
flock($fp, LOCK_UN);
} else {
if (!fwrite($fp, $content)) die('快取寫入失敗(無鎖)');
}
fclose($fp);
echo $content;
} else {
// 快取有效,直接讀取輸出
echo file_get_contents($cache_file);
}
?>
filemtime() 判斷檔案年齡,配合 flock() 排他鎖確保併發安全。ob_start() 捕獲 HTML 輸出,一次性寫入快取並輸出瀏覽器。url.txt 維護股票清單,彈性擴充。file_get_contents(),支援逾時、重試、User-Agent 設定。symfony/cache),提升效能與可維護性。完整原始碼可參考上方程式區塊,若需部署請確認 url.txt 存在且格式正確,且目錄具備寫入權限。