package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"time"
)
// StockData 定义股票数据结构
type StockData struct {
Symbol string `json:"symbol"` // 股票符号
Code string `json:"code"` // 股票代码
Name string `json:"name"` // 股票名称
Trade any `json:"trade"` // 当前价格
PriceChange any `json:"pricechange"` // 价格变动
ChangePercent any `json:"changepercent"` // 涨跌幅
Buy any `json:"buy"` // 买入价
Sell any `json:"sell"` // 卖出价
Settlement any `json:"settlement"` // 结算价
Open any `json:"open"` // 开盘价
High any `json:"high"` // 最高价
Low any `json:"low"` // 最低价
Volume any `json:"volume"` // 成交量
Amount any `json:"amount"` // 成交额
TickTime string `json:"ticktime"` //
PER any `json:"per"` // 市盈率
PB any `json:"pb"` // 市净率
Mktcap any `json:"mktcap"` // 总市值
Nmcap any `json:"nmcap"` // 流通市值
TurnoverRatio any `json:"turnoverratio"` // 换手率
}
// APIResponse API响应结构
type APIResponse struct {
Data []StockData `json:"data"`
}
func main() {
fmt.Println("开始获取新浪财经股票数据...")
// 存储所有股票数据
var allStocks []StockData
page := 1
for {
fmt.Printf("正在获取第 %d 页数据...\n", page)
// 构建API URL
url := fmt.Sprintf("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=%d&num=100&sort=symbol&asc=0&node=hs_a", page)
// 发送HTTP请求
resp, err := http.Get(url)
if err != nil {
log.Printf("第 %d 页请求失败: %v", page, err)
break
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
log.Printf("读取第 %d 页响应失败: %v", page, err)
break
}
// 检查是否返回空数组
if string(body) == "[]" {
fmt.Printf("第 %d 页返回空数组,数据获取完成\n", page)
break
}
// 解析JSON数据
var stocks []StockData
err = json.Unmarshal(body, &stocks)
if err != nil {
log.Printf("解析第 %d 页JSON失败: %v", page, err)
log.Printf("响应内容: %s", string(body))
break
}
// 检查是否获取到数据
if len(stocks) == 0 {
fmt.Printf("第 %d 页没有数据,数据获取完成\n", page)
break
}
// 添加到总数据中
allStocks = append(allStocks, stocks...)
fmt.Printf("第 %d 页获取到 %d 条数据,累计 %d 条数据\n", page, len(stocks), len(allStocks))
// 翻页
page++
// 添加延迟,避免请求过于频繁
time.Sleep(500 * time.Millisecond)
}
// 输出统计信息
fmt.Printf("\n数据获取完成!总共获取到 %d 条股票数据\n", len(allStocks))
// 显示前10条数据作为示例
if len(allStocks) > 0 {
fmt.Println("\n前10条股票数据示例:")
fmt.Println("========================================================================================================")
fmt.Printf("%-10s %-20s %-8s %-8s %-8s %-12s %-12s\n",
"代码", "名称", "当前价", "涨跌", "涨跌幅", "成交量", "成交额")
fmt.Println("========================================================================================================")
for i := 0; i < 10 && i < len(allStocks); i++ {
stock := allStocks[i]
fmt.Printf("%-10s %-20s %-8s %-8s %-8s %-12s %-12s\n",
stock.Symbol, stock.Name, stock.Trade, stock.PriceChange,
stock.ChangePercent, stock.Volume, stock.Amount)
}
}
// 保存数据到文件
saveToFile(allStocks)
}
// saveToFile 将数据保存到JSON文件
func saveToFile(stocks []StockData) {
fileData, err := json.MarshalIndent(stocks, "", " ")
if err != nil {
log.Printf("序列化数据失败: %v", err)
return
}
err = os.WriteFile("stock_data.json", fileData, 0644)
if err != nil {
log.Printf("保存文件失败: %v", err)
return
}
fmt.Printf("\n数据已保存到 stock_data.json 文件\n")
}