pfrederiksen/arccos-api

GitHub: pfrederiksen/arccos-api

Arccos Golf 平台的非官方 Python 客户端与 CLI,通过逆向让用户以编程方式访问个人高尔夫数据。

Stars: 1 | Forks: 0

arccos-api banner

# arccos-api [Arccos Golf](https://arccosgolf.com) 平台的非官方 Python 客户端和 CLI。 Arccos 未提供公开 API。本库是通过逆向工程 Arccos Dashboard Web 应用程序得出的。它让你能够以编程方式完全访问自己的高尔夫数据——包括回合、差点、球杆距离、打球节奏等。 ## 安装 ``` pip install arccos-api ``` 或从源码安装: ``` git clone https://github.com/pfrederiksen/arccos-api.git cd arccos-api pip install -e . ``` 需要 Python >= 3.11。依赖项:`requests`, `click`, `rich`。 ## CLI ### 快速开始 ``` arccos login # authenticate and save credentials arccos rounds # your recent rounds arccos handicap # handicap breakdown arccos clubs # smart club distances ``` ### 命令 | 命令 | 描述 | |---------|-------------| | `arccos login` | 认证并将凭据缓存到 `~/.arccos_creds.json` | | `arccos rounds` | 列出最近的回合,包含日期、成绩、+/-、球场名称 | | `arccos round ` | 逐洞详情(成绩、推杆数、FIR、GIR)及总计 | | `arccos handicap` | 按类别细分的差点(总体、开球、进攻果岭等) | | `arccos clubs` | 智能球杆距离,包含品牌/型号、范围和击球数 | | `arccos bests` | 有史以来的个人最佳记录(最低成绩、最远开球距离等) | | `arccos overview` | 表现摘要——平均成绩 + 差点细分 | | `arccos scoring` | 带有可视化条形图的成绩趋势 | | `arccos courses` | 列出你打过的所有球场 | | `arccos pace` | 按球场分析打球节奏(颜色编码) | | `arccos stats ` | 单轮回合的 Strokes Gained 分析 | | `arccos export` | 将回合导出为 JSON、CSV 或 NDJSON(`--detail` 用于获取逐洞数据) | | `arccos logout` | 清除缓存的凭据 | 每个命令都支持 `--json` 输出原始 JSON,以及 `--help` 查看使用信息。 ### 使用示例 ``` # 回合 arccos rounds # last 20 rounds (with +/- and course names) arccos rounds -n 50 # last 50 arccos rounds --after 2025-01-01 # filter by date arccos rounds --course "pebble" # filter by course name (substring) arccos rounds --json # raw JSON # 回合详情 arccos round 18294051 # hole-by-hole breakdown # Handicap arccos handicap # category breakdown arccos handicap --history # revision history # 球杆距离 arccos clubs # active clubs with make/model arccos clubs --after 2025-01-01 # distances from this year only # 表现 arccos bests # all-time personal bests arccos overview # scoring avg + handicap breakdown arccos scoring # scoring trend with bar chart # 球场 arccos courses # all courses played # 打球节奏 arccos pace # all rounds, slowest courses first arccos pace -n 20 # last 20 rounds only # 导出 arccos export -f csv -o rounds.csv # export to CSV file arccos export --detail # include hole-by-hole data arccos export -f json # dump JSON to stdout arccos export -f ndjson # newline-delimited JSON ``` ### 输出示例 ``` $ arccos clubs Smart Club Distances ╭──────┬──────────────────┬───────┬─────────┬──────────┬───────╮ │ Club │ Model │ Smart │ Longest │ Range │ Shots │ ├──────┼──────────────────┼───────┼─────────┼──────────┼───────┤ │ Dr │ TaylorMade Qi10 │ 252y │ 291y │ 245–263y │ 312 │ │ 3w │ TaylorMade Qi10 │ 228y │ 248y │ 220–235y │ 87 │ │ 5w │ Callaway Paradym │ 208y │ 231y │ 200–215y │ 143 │ │ 4h │ Titleist T200 │ 195y │ 214y │ 188–202y │ 61 │ │ 6i │ Titleist T150 │ 172y │ 190y │ 165–179y │ 94 │ │ 7i │ Titleist T150 │ 160y │ 178y │ 153–167y │ 118 │ │ 8i │ Titleist T150 │ 148y │ 165y │ 141–155y │ 105 │ │ 9i │ Titleist T150 │ 136y │ 152y │ 130–142y │ 97 │ │ Pw │ Titleist T150 │ 124y │ 140y │ 118–130y │ 82 │ │ 50 │ Vokey SM10 │ 108y │ 125y │ 102–114y │ 76 │ │ 54 │ Vokey SM10 │ 88y │ 105y │ 82–94y │ 201 │ │ 58 │ Vokey SM10 │ 64y │ 88y │ 58–70y │ 168 │ ╰──────┴──────────────────┴───────┴─────────┴──────────┴───────╯ $ arccos round 18294051 ╭─── Round 18294051 ────╮ │ Date: 2025-09-14 │ │ Course: Torrey Pines │ │ Score: 79 (+7) │ │ Holes: 18 │ ╰───────────────────────╯ Hole-by-Hole ╭──────┬───────┬───────┬─────┬─────╮ │ Hole │ Score │ Putts │ FIR │ GIR │ ├──────┼───────┼───────┼─────┼─────┤ │ 1 │ 4 │ 2 │ T │ T │ │ 2 │ 5 │ 2 │ F │ F │ │ 3 │ 3 │ 1 │ │ T │ │ ... │ ... │ ... │ ... │ ... │ ├──────┼───────┼───────┼─────┼─────┤ │ Tot │ 79 │ 31 │ │ │ ╰──────┴───────┴───────┴─────┴─────╯ $ arccos handicap Handicap Breakdown ╭────────────┬───────╮ │ Category │ HCP │ ├────────────┼───────┤ │ Overall │ -12.4 │ │ Driving │ -15.1 │ │ Approach │ -18.7 │ │ Short Game │ -14.3 │ │ Putting │ -6.2 │ ╰────────────┴───────╯ $ arccos pace -n 10 Pace of Play — 10 rounds across 6 courses Overall avg: 4h 22m By Course (slowest first) ╭────┬──────────┬───────────────────────┬────────╮ │ │ Avg Time │ Course │ Rounds │ ├────┼──────────┼───────────────────────┼────────┤ │ 🔴 │ 5h 10m │ Bethpage Black │ 2 │ │ 🟡 │ 4h 45m │ Torrey Pines │ 3 │ │ 🟢 │ 3h 50m │ Bandon Dunes │ 2 │ │ 🟢 │ 3h 35m │ Chambers Bay │ 1 │ ╰────┴──────────┴───────────────────────┴────────╯ ``` ### 环境变量 通过设置以下变量跳过登录提示: ``` export ARCCOS_EMAIL="you@example.com" export ARCCOS_PASSWORD="your_password" arccos rounds ``` ## Python 库 ``` from arccos import ArccosClient client = ArccosClient(email="you@example.com", password="your_password") # 凭证已缓存在 ~/.arccos_creds.json。自动静默刷新。 # 回合 rounds = client.rounds.list(limit=10) for r in rounds: print(f"{r['startTime'][:10]} score={r['noOfShots']} {r.get('courseName', '')}") # 回合详情(包含嵌入式逐洞数据) rd = client.rounds.get(rounds[0]["roundId"]) for hole in rd["holes"]: print(f" Hole {hole['holeId']}: {hole['noOfShots']} shots, {hole['putts']} putts") # Handicap 细分 hcp = client.handicap.current() print(f"Overall: {hcp['userHcp']:.1f}") print(f"Driving: {hcp['driveHcp']:.1f}") # 球杆距离(返回 clubId 作为球包位置 — 参见 bag API 进行名称映射) for club in client.clubs.smart_distances(): dist = club["smartDistance"]["distance"] print(f" Club {club['clubId']}: {dist:.0f}y") # Bag 配置(映射 clubId → clubType + 品牌/型号) profile = client._http.get(f"/users/{client.user_id}") bag = client.clubs.bag(str(profile["bagId"])) for club in bag["clubs"]: if club.get("isDeleted") != "T": print(f" {club['clubMakeOther']} {club['clubModelOther']}") # 已打球场 for course in client.courses.played(): print(f" {course.get('name', course['courseId'])}") # 打球节奏分析 pace = client.rounds.pace_of_play() print(f"Overall avg: {pace['overall_avg_display']}") for c in pace["course_averages"][:5]: print(f" {c['avg_display']} {c['course']}") # 个人最佳成绩 bests = client.stats.personal_bests() ``` ## API 参考 完整的 OpenAPI 3.1 规范:[`docs/openapi.yaml`](docs/openapi.yaml) ### 认证 所有认证调用均发往 `https://authentication.arccosgolf.com`。 | 步骤 | 端点 | Body | 返回值 | |------|----------|------|---------| | 1. 获取 access key | `POST /accessKeys` | `{"email", "password", "signedInByFacebook": "F"}` | `{"userId", "accessKey", "secret"}` | | 2. 获取 JWT | `POST /tokens` | `{"userId", "accessKey"}` | `{"userId", "token"}` | JWT 约在 3 小时后过期。`accessKey` 有效期约为 180 天。再次调用 `POST /tokens` 即可刷新。 ### 端点 所有数据调用均发往 `https://api.arccosgolf.com`,并带有 `Authorization: Bearer `。 | 资源 | 方法 | 路径 | |----------|--------|------| | 用户资料 | GET | `/users/{userId}` (包含 `bagId`, `bags[]`) | | 球包 / 球杆 | GET | `/users/{userId}/bags/{bagId}` (球杆配置,含品牌/型号) | | 回合列表 | GET | `/users/{userId}/rounds?offSet=0&limit=200&roundType=flagship` | | 回合详情 | GET | `/users/{userId}/rounds/{roundId}` (包含 `holes[]` 和 `shots[]`) | | 差点 | GET | `/users/{userId}/handicaps/latest` | | 差点历史 | GET | `/users/{userId}/handicaps?rounds=20` | | 智能距离 | GET | `/v4/clubs/user/{userId}/smart-distances` | | 打过的球场 | GET | `/users/{userId}/coursesPlayed` | | 球场元数据 | GET | `/courses/{courseId}?courseVersion=1` | | 球场搜索 | GET | `/v2/courses?search={query}` | | 个人最佳 | GET | `/users/{userId}/personalBests?tags=allTimeBest` | ### 关键数据结构 **Round** (来自 `GET /users/{id}/rounds/{roundId}`): ``` { "roundId": 18294051, "courseId": 12450, "courseVersion": 4, "startTime": "2025-09-14T15:30:00.000000Z", "endTime": "2025-09-14T20:15:00.000000Z", "noOfShots": 79, "noOfHoles": 18, "holes": [ { "holeId": 1, "noOfShots": 4, "putts": 2, "isGir": "T", "isFairWay": "T", "shots": [{"clubId": 1, "clubType": 1, "distance": 255.0}] } ] } ``` **Smart distance** (来自 `GET /v4/clubs/user/{id}/smart-distances`): ``` { "clubId": 1, "smartDistance": {"distance": 252.3, "unit": "yd"}, "longest": {"distance": 291.0, "unit": "yd"}, "range": {"low": 245.0, "high": 263.0, "unit": "yd"}, "usage": {"count": 312} } ``` **Bag club** (来自 `GET /users/{id}/bags/{bagId}`): ``` { "clubId": 1, "clubType": 1, "clubMakeOther": "TaylorMade", "clubModelOther": "Qi10", "isDeleted": "F" } ``` ## 开发 ``` python3 -m venv .venv source .venv/bin/activate pip install -e ".[dev]" pytest # tests with coverage (88%+, 125 tests) ruff check arccos/ # lint mypy arccos/ # type check ``` 覆盖率报告:`htmlcov/index.html`。最低阈值:80%(在 `pyproject.toml` 中配置)。 ## 安全 - 凭据缓存在 `~/.arccos_creds.json` 中(模式为 `0600`——仅所有者可读写)。该文件包含你的 access key(约 180 天有效期)和 JWT token。请妥善保管。 - 所有 API 通信均使用带有 TLS 证书验证的 HTTPS。 - `arccos logout` 会删除本地凭据文件,但**不会**撤销服务器端的 token。如果你怀疑凭据已泄露,请更改你的 Arccos 密码。 - 导出命令将输出路径限制在你的主目录或当前工作目录。 ## 已知缺失 - [ ] SGA 端点认证(`/v2/sga/shots/` 返回 40102——可能需要通过 `secret` 进行 HMAC) - [ ] 社交/动态流端点(`/users/{id}/feed`、关注等) - [ ] 练习场数据(`roundType=range`) - [ ] 异步客户端(`httpx`) 欢迎提交 PR。 ## 免责声明 不隶属于、不由 Arccos Golf LLC 认可或与其有关联。 仅使用你自己的账户凭据。本项目用于个人数据访问和研究。 MIT License。
标签:API客户端, Arccos Golf, CLI, Click, CSV, JSON, Python, Rich, URL抓取, WiFi技术, 云资产清单, 代码示例, 体育统计, 差点分析, 数据分析, 数据导出, 数据抓取, 文档结构分析, 无后门, 杆身距离, 比赛记录, 运动科技, 逆向工具, 逆向工程, 非官方API, 高尔夫数据