最近在做一个金融相关的项目,需要对接股票,外汇和黄金的行情数据。在网上找了一圈,发现了一个还算稳定的数据源。“脉动行情数据” 今天就把对接过程中用到的“获取实时数据接口”这部分整理出来,分享给大家。
先说重点
这个接口是HTTP的GET请求,比较简单。不过有几个地方需要注意:
- 频率限制:每个产品每秒可请求3次,完全够用了
- 压缩传输:建议启用gzip压缩,能省不少流量
接口基本信息
- 地址:
http://39.107.99.235:1008/getQuote.php - 方式:GET
- 参数:就一个
code,传产品代码就行 - 返回:JSON格式
上代码,直接开干
我习惯先写个工具类,后面用起来方便:
<?php
/**
* 行情数据接口封装类
* 作者:我自己
* 日期:2024年1月
*/
class MarketApi {
// 数据演示站
private $apiUrl = 'http://39.107.99.235:1008/market';
// 接口地址
private $apiUrl = 'http://39.107.99.235:1008/getQuote.php';
// 上次请求时间记录(用于控制频率)
private static $lastRequestTime = [];
/**
* 获取单个产品的行情数据
* @param string $code 产品代码,比如 btcusdt, ethusdt
* @return array
*/
public function getQuote($code) {
// 检查请求频率
if (!$this->checkRateLimit($code)) {
return [
'success' => false,
'message' => '请求太频繁了,请稍后再试'
];
}
// 构建请求URL
$url = $this->apiUrl . '?code=' . urlencode($code);
// 设置请求头,启用gzip压缩
$headers = [
'Accept-Encoding: gzip',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
];
// 发起请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
$error = curl_error($ch);
curl_close($ch);
return [
'success' => false,
'message' => '请求失败:' . $error
];
}
curl_close($ch);
// 处理gzip压缩的响应
if (substr($response, 0, 2) == "\x1f\x8b") {
$response = gzdecode($response);
}
// 解析响应数据
$result = json_decode($response, true);
if ($httpCode != 200) {
return [
'success' => false,
'message' => '接口返回错误,HTTP码:' . $httpCode,
'data' => $result
];
}
if (json_last_error() !== JSON_ERROR_NONE) {
return [
'success' => false,
'message' => 'JSON解析失败:' . json_last_error_msg()
];
}
// 记录本次请求时间
$this->recordRequestTime($code);
return [
'success' => true,
'data' => $result
];
}
/**
* 批量获取多个产品行情
* @param array $codes 产品代码数组
* @return array
*/
public function getBatchQuotes($codes) {
$results = [];
foreach ($codes as $code) {
// 每个请求之间稍微停顿一下,避免触发限流
usleep(100000); // 0.1秒
$result = $this->getQuote($code);
$results[$code] = $result;
}
return $results;
}
/**
* 检查请求频率
* @param string $code 产品代码
* @return bool
*/
private function checkRateLimit($code) {
if (!isset(self::$lastRequestTime[$code])) {
return true;
}
$lastTime = self::$lastRequestTime[$code];
$currentTime = microtime(true);
$interval = $currentTime - $lastTime;
// 确保两次请求间隔至少0.34秒(略高于1/3秒)
return $interval >= 0.34;
}
/**
* 记录请求时间
* @param string $code 产品代码
*/
private function recordRequestTime($code) {
self::$lastRequestTime[$code] = microtime(true);
}
/**
* 提取主要行情信息(简化版)
* @param array $apiData 接口返回的原始数据
* @return array
*/
public function extractMainData($apiData) {
if (empty($apiData['data']['body'])) {
return null;
}
$body = $apiData['data']['body'];
return [
'code' => $body['StockCode'] ?? '',
'latest_price' => $body['Price'] ?? 0,
'open_price' => $body['Open'] ?? 0,
'high_price' => $body['High'] ?? 0,
'low_price' => $body['Low'] ?? 0,
'volume' => $body['TotalVol'] ?? 0,
'change' => $body['Diff'] ?? 0,
'change_rate' => $body['DiffRate'] ?? 0,
'update_time' => $body['Time'] ?? '',
'buy_price' => $body['BP1'] ?? 0,
'buy_volume' => $body['BV1'] ?? 0,
'sell_price' => $body['SP1'] ?? 0,
'sell_volume' => $body['SV1'] ?? 0
];
}
}
使用示例
<?php
// 引入上面的类
require_once 'MarketApi.php';
// 创建实例
$marketApi = new MarketApi();
// 示例1:获取单个产品行情
echo "=== 获取BTC行情 ===\n";
$btcResult = $marketApi->getQuote('btcusdt');
if ($btcResult['success']) {
$mainData = $marketApi->extractMainData($btcResult['data']);
echo "产品代码:{$mainData['code']}\n";
echo "最新价格:{$mainData['latest_price']}\n";
echo "涨跌幅:{$mainData['change_rate']}%\n";
echo "更新时间:{$mainData['update_time']}\n";
echo "买一价:{$mainData['buy_price']}\n";
echo "卖一价:{$mainData['sell_price']}\n";
echo "成交量:{$mainData['volume']}\n";
} else {
echo "获取失败:{$btcResult['message']}\n";
}
// 示例2:批量获取
echo "\n=== 批量获取多个产品 ===\n";
$codes = ['ethusdt', 'bchusdt', 'xrpusdt'];
$batchResults = $marketApi->getBatchQuotes($codes);
foreach ($batchResults as $code => $result) {
if ($result['success']) {
$data = $marketApi->extractMainData($result['data']);
echo "{$code}: {$data['latest_price']} ({$data['change_rate']}%)\n";
} else {
echo "{$code}: 获取失败\n";
}
}
// 示例3:查看完整的接口返回数据
echo "\n=== 查看完整数据结构 ===\n";
$fullResult = $marketApi->getQuote('ethusdt');
if ($fullResult['success']) {
// 这里可以打印完整数据或者保存到数据库
// print_r($fullResult['data']);
echo "获取成功,数据已收到\n";
}
实际开发中的经验
1. 数据库存储
如果要做行情分析,建议存数据库,如果不用那就算了:
class MarketDataSaver {
private $db;
public function __construct($db) {
$this->db = $db;
}
public function saveQuoteData($code, $quoteData) {
$mainData = $quoteData['data']['body'] ?? [];
if (empty($mainData)) {
return false;
}
$sql = "INSERT INTO market_quotes
(stock_code, price, open_price, high_price, low_price,
volume, change_amount, change_rate, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $this->db->prepare($sql);
return $stmt->execute([
$mainData['StockCode'],
$mainData['Price'],
$mainData['Open'],
$mainData['High'],
$mainData['Low'],
$mainData['TotalVol'],
$mainData['Diff'],
$mainData['DiffRate'],
$mainData['Time']
]);
}
}
总结
这个接口用起来还算简单,主要是注意频率控制和错误处理。如果要更高频率的数据,建议用他们的WebSocket接口。
上面的代码是我实际项目中提炼出来的,可以直接用。如果有问题,欢迎在评论区讨论。
注意:这个接口需要授权才能用,别直接拿代码去跑,先联系客服加白名单。
希望对大家有帮助!