为啥我突然想写这个?
前几天跑完黄河口马拉松,朋友圈都在晒成绩,我也想去官网查,结果那个页面加载慢得要命,想着自己好歹是个写Go的,干脆写个小工具,命令行里嗖一下就能查到成绩,多带劲。
说实话,马拉松成绩查询这个需求挺简单的:输入参赛号,返回完赛时间、净成绩、枪声成绩、排名这些信息,但真要写出来,从HTTP请求到JSON解析,再到数据展示,一套流程跑下来,还挺锻炼人的。
第一步:找到数据接口
黄河口马拉松官网的成绩查询,本质上是向某个API发POST请求,我用浏览器开发者工具(F12)抓了一下,发现其实很简单:

POST https://huanghekou.marathon.com/result/query
Content-Type: application/json
{
"bib": "A12345",
"type": "marathon"
}
返回的JSON结构大概长这样:
{
"code": 200,
"data": {
"name": "张三",
"bib": "A12345",
"gun_time": "03:45:22",
"net_time": "03:42:18",
"rank": 128,
"category": "男子全程",
"category_rank": 45
}
}
注意:实际接口可能加密,这里只是示意,但大多数国内马拉松查询接口,基本都这个套路。
第二步:用Go写查询函数
直接上代码,不过我会边写边解释,你跟着走一遍就懂了。
建个结构体,存成绩数据
type MarathonResult struct {
Name string `json:"name"`
Bib string `json:"bib"`
GunTime string `json:"gun_time"`
NetTime string `json:"net_time"`
Rank int `json:"rank"`
Category string `json:"category"`
CategoryRank int `json:"category_rank"`
}
这里用了JSON标签,方便直接把API返回的JSON映射过来,不写这玩意儿也行,但写了就省得手动拆字段了。
写查询逻辑
func QueryResult(bib string) (*MarathonResult, error) {
url := "https://huanghekou.marathon.com/result/query"
reqBody := map[string]string{
"bib": bib,
"type": "marathon",
}
jsonData, _ := json.Marshal(reqBody)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("查询失败: %v", err)
}
defer resp.Body.Close()
var result struct {
Code int `json:"code"`
Data MarathonResult `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&result)
if result.Code != 200 {
return nil, fmt.Errorf("服务器返回错误码: %d", result.Code)
}
return &result.Data, nil
}
这里有个坑:延迟加载,有些马拉松系统的查询接口,成绩是按批次开放的,你查太早了可能返回空数据,我一般等比赛结束2小时后才查。
第三步:命令行里跑起来
我想在终端直接输个参赛号就出结果,所以写了个命令行版本:
func main() {
fmt.Print("请输入参赛号: ")
reader := bufio.NewReader(os.Stdin)
bib, _ := reader.ReadString('\n')
bib = strings.TrimSpace(bib)
result, err := QueryResult(bib)
if err != nil {
fmt.Printf("出错了: %v\n", err)
return
}
// 漂亮的表格输出
fmt.Println("\n🏃 黄河口马拉松成绩单 🏃")
fmt.Println("==============================")
table := [][]string{
{"姓名", result.Name},
{"参赛号", result.Bib},
{"枪声成绩", result.GunTime},
{"净成绩", result.NetTime},
{"总排名", strconv.Itoa(result.Rank)},
{"组别", result.Category},
{"组内排名", strconv.Itoa(result.CategoryRank)},
}
for _, row := range table {
fmt.Printf("| %-10s | %s\n", row[0], row[1])
}
}
你跑起来大概会看到这种效果:
请输入参赛号: A12345
🏃 黄河口马拉松成绩单 🏃
==============================
| 姓名 | 张三
| 参赛号 | A12345
| 枪声成绩 | 03:45:22
| 净成绩 | 03:42:18
| 总排名 | 128
| 组别 | 男子全程
| 组内排名 | 45
看着是不是挺像回事儿? 虽然界面有点粗,但自己用着顺手。
搞个更酷的:加个表格式输出
上面那个输出有点乱,咱们换成真正表格,用制表符对齐:
func printTable(results []MarathonResult) {
fmt.Println("+----------+----------+----------+---------+------+------------+")
fmt.Println("| 姓名 | 参赛号 | 枪声成绩 | 净成绩 | 排名 | 组别 |")
fmt.Println("+----------+----------+----------+---------+------+------------+")
for _, r := range results {
fmt.Printf("| %-8s | %-8s | %-8s | %-7s | %-4d | %-10s |\n",
r.Name, r.Bib, r.GunTime, r.NetTime, r.Rank, r.Category)
}
fmt.Println("+----------+----------+----------+---------+------+------------+")
}
这样查多个人成绩时,一列列排得整整齐齐,强迫症患者的福音。
实际使用中的几个小坑
- 网络延迟:马拉松查询接口经常崩,建议加超时
client := &http.Client{Timeout: 10 * time.Second}
- 中文乱码:有些接口返回GBK编码,得转UTF-8
import "golang.org/x/text/encoding/simplifiedchinese" decoder := simplifiedchinese.GBK.NewDecoder() utf8Data, _ := decoder.Bytes(respBody)
- 查询次数限制:别写个死循环去刷,会被封IP,我一般间隔3秒查一次。
要不要做成Web服务?
如果你想让跑友也能用,可以加个HTTP接口:
http.HandleFunc("/query", func(w http.ResponseWriter, r *http.Request) {
bib := r.URL.Query().Get("bib")
result, err := QueryResult(bib)
if err != nil {
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
json.NewEncoder(w).Encode(result)
})
http.ListenAndServe(":8080", nil)
然后别人就可以用浏览器访问 http://你的IP:8080/query?bib=A12345 来查成绩了。
不过千万别把这个服务部署到公网对外,一来版权问题,二来人家官方封你接口,自己本地玩玩就好。
黄河口马拉松的成绩查询,说到底就是一个HTTP请求加JSON解析,用Go写起来特别顺手,标准库就搞定了,连第三方依赖都不用加,你下次跑完马拉松,也可以试试自己写一个——边等成绩边写代码,跑完刚好工具跑通。
本文来自作者[kyadmin]投稿,不代表678体育 - 全网热门体育赛事高清直播平台立场,如若转载,请注明出处:http://66weibo.cn/ty/758.html
评论列表(4条)
我是678体育 - 全网热门体育赛事高清直播平台的签约作者“kyadmin”!
希望本篇文章《黄河口马拉松成绩查询,用Golang写个查询器,其实没那么难》能对你有所帮助!
本站[678体育 - 全网热门体育赛事高清直播平台]内容主要涵盖:678体育,678体育官网,678赛事直播
本文概览:为啥我突然想写这个?前几天跑完黄河口马拉松,朋友圈都在晒成绩,我也想去官网查,结果那个页面加载慢得要命,想着自己好歹是个写Go的,干...