80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
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
|
||
}
|