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 }