php不适合实时股票抓取,因其无常驻内存能力,仅能轮询且易被限流反爬;免费接口多延迟15分钟,js动态渲染内容php无法执行;需模拟浏览器头、正则解析返回值;高实时需求应由python/node.js采集存redis,php仅读取。

PHP 本身不适合做实时股票数据抓取——它没有常驻内存能力,HTTP 请求是短生命周期的,所谓“实时”只能靠轮询,而高频轮询既被接口限流,又容易触发反爬。
为什么 file_get_contents 或 cURL 抓不到实时行情
多数免费股票接口(如新浪、腾讯、Yahoo Finance)返回的是延迟 15 分钟的数据;部分标榜“实时”的接口(如 EastMoney 的 Websocket 页面)实际依赖前端 JS 动态拉取,PHP 后端无法执行 JS,直接请求 HTML 拿到的是静态占位符或空值。
- 新浪股票接口
http://hq.sinajs.cn/list=sh600519返回 JS 变量赋值语句,需用正则提取,且仅支持 A 股代码,无港股/美股 - 腾讯接口
https://qt.gtimg.cn/q=sh600519类似,但 HTTPS 下可能被重定向或返回 403 - 直接
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)不解决反爬,很多站点会校验User-Agent和Referer
用 curl_init 模拟浏览器请求的必要配置
绕过基础反爬,至少要补全三要素:User-Agent、Referer、Accept-Encoding。缺一不可,否则大概率返回空内容或 403。
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')-
curl_setopt($ch, CURLOPT_REFERER, 'https://finance.sina.com.cn/')(必须和目标域名一致或上级路径) -
curl_setopt($ch, CURLOPT_ENCODING, 'gzip')并配合curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) - 超时设为
CURLOPT_TIMEOUT => 5,避免卡死;失败时不抛错,用curl_error($ch)判断
解析新浪接口返回值的正则写法(以 sh600519 为例)
新浪返回形如 var hq_str_sh600519="贵州茅台,1825.000,1827.000,1822.000,1828.000,1821.000,1823.000,1824.000,1234567,2234567890,...",注意逗号分隔、中文名在前、字段顺序固定。
立即学习“PHP免费学习笔记(深入)”;
$content = file_get_contents('http://hq.sinajs.cn/list=sh600519');
preg_match('/"([^"]+)"/', $content, $matches);
if (isset($matches[1])) {
$fields = explode(',', $matches[1]);
$data = [
'name' => $fields[0],
'last_close' => $fields[1], // 昨收
'open' => $fields[2], // 今开
'high' => $fields[3], // 最高
'low' => $fields[4], // 最低
'now' => $fields[5], // 当前价
'volume' => $fields[8], // 成交量(手)
'amount' => $fields[9], // 成交额(元)
];
}
字段顺序不能硬编码记错——不同接口(如港股 hk00700)返回字段数不同,建议先 print_r($fields) 看清结构再取值。
真正需要“实时”时,PHP 只能做中转,别硬扛
如果业务要求秒级更新(比如盯盘提醒),PHP 不该承担采集任务。正确做法是:
- 用 Python +
websocket-client或 Node.js 连接真正的实时源(如聚宽、AKShare、或者券商提供的 WebSocket 接口) - 把数据存进 Redis,设置过期时间(如
EXPIRE stock:sh600519 30) - PHP 只做读取:
$redis->get('stock:sh600519'),不碰网络请求 - 若必须 PHP 采集,加
sleep(30)控制频率,避免被封 IP;并用file_put_contents缓存结果,失败时返回缓存值
字段含义模糊、接口随时失效、IP 被限、gzip 解压失败、中文乱码——这些不是边缘情况,是每次部署都会遇到的默认状态。











