This commit is contained in:
2026-02-26 16:53:51 +08:00
parent f29265c0e4
commit 1e4a361f3c
5 changed files with 144 additions and 5 deletions

View File

@@ -0,0 +1,79 @@
package libs
import (
"fmt"
"io"
"net/http"
"strings"
"time"
)
// GetSinaStockPrice 获取新浪财经某只股票的最新价
// 股票代码格式: 沪市为 sh + 代码,深市为 sz + 代码,例如 "sh600519"
func GetSinaStockPrice(stockCode string) (float64, error) {
tmp := strings.Split(strings.ToLower(stockCode), ".")
code := tmp[1] + tmp[0]
// 1. 构建请求URL
url := fmt.Sprintf("http://hq.sinajs.cn/list=%s", code)
// 2. 创建HTTP客户端并设置超时避免长时间阻塞
client := &http.Client{
Timeout: 5 * time.Second,
}
// 3. 创建请求并设置Referer增加稳定性 [citation:5]
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return 0, fmt.Errorf("创建请求失败: %w", err)
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
req.Header.Set("Referer", "https://finance.sina.com.cn")
// 4. 发送请求
resp, err := client.Do(req)
if err != nil {
return 0, fmt.Errorf("HTTP请求失败: %w", err)
}
defer resp.Body.Close()
// 5. 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0, fmt.Errorf("读取响应体失败: %w", err)
}
// 6. 解析数据
// 响应示例: var hq_str_sh600519="贵州茅台,1710.00,1705.00,1720.00,...";
dataStr := string(body)
// 检查是否获取到数据
if !strings.Contains(dataStr, "hq_str_") {
return 0, fmt.Errorf("返回数据格式异常或股票代码不存在")
}
// 提取引号内的部分
start := strings.Index(dataStr, "\"")
end := strings.LastIndex(dataStr, "\"")
if start == -1 || end == -1 || end <= start {
return 0, fmt.Errorf("无法解析数据格式")
}
content := dataStr[start+1 : end]
// 按逗号分割
fields := strings.Split(content, ",")
// 检查字段数量是否足够 (至少需要4个字段来获取价格)
if len(fields) < 4 {
return 0, fmt.Errorf("返回数据字段不足: %v", fields)
}
// 当前价格是第4个字段 (索引为3) [citation:8][citation:9]
priceStr := fields[3]
var price float64
_, err = fmt.Sscanf(priceStr, "%f", &price)
if err != nil {
return 0, fmt.Errorf("解析价格失败: %s, 错误: %w", priceStr, err)
}
return price, nil
}