是的,OWER API项目我又又又重构了,这是第三版了(
OWER-API v3 是一个基于 Node.js + TypeScript 的 Overwatch 2(守望先锋 2)玩家生涯数据查询 API 服务。
它接收一个战网账号(BattleTag),自动解析出 Blizzard 玩家 ID,抓取 Overwatch 官方公开的 Career 页面,使用 Cheerio 解析页面内容,并以结构化 JSON 的形式返回玩家数据。
说明:本项目不是 Blizzard 官方 API,也未使用任何官方私有接口。所有数据均来自 Overwatch 官方公开的 Career 页面(
https://overwatch.blizzard.com/.../career/...),通过公开页面抓取 + 解析得到。
BattleTag → 解析 Player ID → 抓取 Career 页面 HTML → Cheerio 解析 → 结构化 JSON
- 客户端传入 BattleTag(如
Player#1234)。 - 服务请求官方
career/{tag}地址并跟随重定向,从最终 URL 中解析出玩家 ID;可选地将映射持久化到数据库以便复用。 - 使用玩家 ID 抓取 Career 页面 HTML(命中缓存则跳过官网请求)。
- 使用 Cheerio 解析 HTML,提取基础信息、竞技段位、常用英雄、游戏数据等。
- 返回统一结构的 JSON,并写入缓存。
- BattleTag 自动解析为 Blizzard 玩家 ID
- 玩家生涯数据查询(基础信息、竞技段位、常用英雄、游戏数据统计)
- 游戏模式统计查询(按平台 / 模式 / 数据类型)
- 英雄统计查询(按平台 / 模式 / 英雄)
- 多级缓存机制
- Redis JSON 结果缓存
- HTML 原始页面缓存(Brotli 压缩、磁盘存储)
- Player ID 持久化(SQLite / PostgreSQL 可选)
- Swagger / OpenAPI 在线文档(
/docs) - 请求链路追踪(
X-Request-ID) - 统一错误码与错误响应结构
- 基于 IP 的请求限流
- 密钥鉴权(
authorization请求头) - TypeScript 类型安全(
strict模式,ESM) - Node.js Cluster 多进程支持
- Vitest 单元 / 集成测试
| 技术 | 用途 |
|---|---|
| Node.js (ESM) | 运行时 |
| TypeScript | 类型系统 |
| Express 4 | Web 框架 |
| Cheerio | HTML 解析 |
| Axios | HTTP 客户端 |
| ioredis | Redis 客户端(JSON 缓存) |
| node:zlib (Brotli) | HTML 页面压缩缓存 |
| node:sqlite / pg | Player ID 持久化(SQLite / PostgreSQL) |
| log4js | 日志 |
| nanoid | 请求 ID 生成 |
| swagger-ui-express | API 文档 |
| Vitest | 测试 |
| tsx | 开发运行 / 热重载 |
flowchart TD
Client[Client] --> API[Express API]
API --> MW[Middlewares: requestId / accessLog / rateLimit / auth]
MW --> Controller[Controller]
Controller --> NameSearch[Player ID 解析]
Controller --> Service[Service]
Service --> RedisCache{Redis JSON 缓存}
RedisCache -->|命中| Client
RedisCache -->|未命中| Fetch[fetchCareerPage]
Fetch --> HtmlCache{HTML Brotli 缓存}
HtmlCache -->|命中| Parser[Cheerio Parser]
HtmlCache -->|未命中| Blizzard[Blizzard Career 页面]
Blizzard --> Parser
Parser --> Service
Service -->|写缓存| RedisCache
Service --> Client
src/
├── app/ # 应用装配层:进程入口 (server.ts) 与路由表 (routes.ts)
├── infrastructure/ # 基础设施层:配置、日志、缓存、持久化
├── modules/ # 业务模块:career / games / heroes(controller-service-parser)
├── shared/ # 跨模块共享:错误体系、中间件、工具函数
├── types/ # 全局 TypeScript 类型声明
└── data/ # 静态数据:heroes.json / typeToCategoryIdMap.json
| 目录 | 职责 |
|---|---|
app/ |
cluster 启动入口、Master/Worker 生命周期、Express 装配、路由注册 |
infrastructure/ |
与业务无关的技术设施:config(配置)、logger(日志)、cache(Redis + HTML 缓存)、persistence(Player ID 仓储) |
modules/ |
核心业务,按领域垂直切分;每个模块内部分为 controller(入参校验/编排)、service(流程与缓存)、parser(HTML 解析) |
shared/ |
错误类与错误码、Express 中间件(链路追踪 / 访问日志 / 鉴权 / 限流)、通用工具 |
types/ |
领域与 API 类型的集中声明 |
data/ |
英雄字典与统计类型映射的静态 JSON |
更详细的架构说明见 docs/ARCHITECTURE.md。
- Node.js >= 22.5(依赖内置
node:sqlite) - pnpm
pnpm installcp .env.example .env
# 按需修改 .env开发模式(热重载):
pnpm dev生产模式:
pnpm build
node dist/app/server.js启动后默认监听 http://127.0.0.1:16525。
完整说明见 docs/CONFIGURATION.md,以下为常用项:
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT |
16525 |
服务端口 |
HOST |
127.0.0.1 |
监听地址 |
LOG_LEVEL |
info |
日志等级(trace / debug / info / warn / error) |
AUTH_SECRET |
(示例值) | 接口鉴权密钥,生产环境务必自行修改 |
CLUSTER_CORE |
0 |
Worker 进程数,0 表示使用 CPU 核数 |
CLUSTER_CRASHED_LIMIT |
20 |
Worker 崩溃累计上限,达到后整体退出 |
API_LIMIT_TIME_WINDOW |
60000 |
限流时间窗口(毫秒) |
API_LIMIT_MAX_REQUESTS |
100 |
限流窗口内最大请求数(多进程下按 Worker 数均摊) |
API_LIMIT_WHITE_LIST |
127.0.0.1,localhost |
限流白名单 IP |
REDIS_ENABLE |
false |
是否启用 Redis JSON 缓存 |
REDIS_HOST |
127.0.0.1 |
Redis 地址 |
REDIS_PORT |
6379 |
Redis 端口 |
REDIS_PASSWORD |
(空) | Redis 密码 |
CAREER_CACHE_TTL |
21600 |
career 结果缓存 TTL(秒) |
GAMES_CACHE_TTL |
21600 |
games 结果缓存 TTL(秒) |
HEROES_CACHE_TTL |
21600 |
heroes 结果缓存 TTL(秒) |
HTML_CACHE_ENABLE |
true |
是否启用 HTML 页面缓存 |
HTML_CACHE_DIR |
./cache/html |
HTML 缓存目录 |
HTML_CACHE_TTL |
21600 |
HTML 缓存 TTL(秒) |
HTML_CACHE_CLEAN_INTERVAL |
3600 |
HTML 缓存后台清理周期(秒) |
DB_TYPE |
none |
Player ID 持久化类型:none / sqlite / postgresql |
SQLITE_FILE |
./data/playerId.sqlite |
SQLite 文件路径 |
POSTGRES_HOST |
127.0.0.1 |
PostgreSQL 地址 |
POSTGRES_PORT |
5432 |
PostgreSQL 端口 |
POSTGRES_USER |
postgres |
PostgreSQL 用户 |
POSTGRES_PASSWORD |
(空) | PostgreSQL 密码 |
POSTGRES_DATABASE |
ower_api |
PostgreSQL 数据库名 |
基础地址:/v3/api
所有接口均需在请求头携带鉴权密钥:
authorization: <AUTH_SECRET>
响应统一结构:成功为 { success: true, data, requestId, timestamp },失败为 { success: false, error: { code, message, ... }, timestamp }。完整说明见 docs/API.md。
查询玩家生涯信息。
| 参数 | 必填 | 默认 | 说明 |
|---|---|---|---|
battle_tag |
是 | — | 战网账号,格式 名称#数字 |
curl "http://127.0.0.1:16525/v3/api/career?battle_tag=Player%231234" \
-H "authorization: <AUTH_SECRET>"{
"success": true,
"data": {
"baseInfo": {
"battleTag": "Player#1234",
"playerName": "Player",
"endorsement": 3
},
"competitive": {},
"commonHeroes": [],
"gameStats": {}
},
"requestId": "l757TrsB9ol2I5m9Rb87T",
"timestamp": 1783702722638
}查询游戏模式数据排行。
| 参数 | 必填 | 默认 | 说明 |
|---|---|---|---|
battle_tag |
是 | — | 战网账号 |
platform |
否 | pc |
pc 或 console |
gamemode |
否 | quickplay |
quickplay 或 competitive |
type |
否 | time-played |
数据类型(见 typeToCategoryIdMap.json) |
curl "http://127.0.0.1:16525/v3/api/games?battle_tag=Player%231234&type=time-played" \
-H "authorization: <AUTH_SECRET>"查询指定英雄的详细数据。
| 参数 | 必填 | 默认 | 说明 |
|---|---|---|---|
battle_tag |
是 | — | 战网账号 |
platform |
否 | pc |
pc 或 console |
gamemode |
否 | quickplay |
quickplay 或 competitive |
hero_id |
否 | 0 |
英雄 ID(见 heroes.json,0 为全英雄) |
curl "http://127.0.0.1:16525/v3/api/heroes?battle_tag=Player%231234&hero_id=1" \
-H "authorization: <AUTH_SECRET>"服务启动后,访问:
http://127.0.0.1:16525/docs
即可查看交互式 Swagger UI;原始 OpenAPI JSON 位于 /docs.json。
服务采用两级缓存 + 官网回源的数据流:
flowchart TD
A[请求] --> B{Redis JSON 缓存}
B -->|命中| Z[返回 JSON]
B -->|未命中| C{HTML Brotli 缓存}
C -->|命中| D[Cheerio 解析]
C -->|未命中| E[Blizzard Career 页面]
E --> D
D --> F[写入 Redis]
F --> Z
- Redis JSON 缓存:缓存解析后的最终 JSON 结果,命中即直接返回,跳过抓取与解析。
- HTML Brotli 缓存:缓存原始页面 HTML(Brotli 压缩后落盘),命中则跳过官网请求,仅执行解析。
为什么缓存 HTML:
- 降低对 Overwatch 官网的请求压力
- 便于 Parser 调试(可用缓存的真实页面反复验证解析逻辑)
- 提升响应速度(省去一次跨网请求)
详见 docs/CACHE.md。
常用命令:
pnpm dev # 开发模式(热重载)
pnpm typecheck # 类型检查(tsc --noEmit)
pnpm test # 运行测试
pnpm test:coverage # 运行测试并生成覆盖率报告
pnpm build # 编译到 dist/更多开发说明见 docs/DEVELOPMENT.md。
ower-api-v3/
├── .github/
│ └── workflows/
│ └── test.yml
├── docs/
│ ├── ARCHITECTURE.md
│ ├── API.md
│ ├── CONFIGURATION.md
│ ├── CACHE.md
│ ├── DEVELOPMENT.md
│ ├── DEPLOYMENT.md
│ └── FAQ.md
├── src/
│ ├── app/
│ │ ├── routes.ts
│ │ └── server.ts
│ ├── docs/
│ │ ├── openapi/
│ │ │ ├── responses/index.yaml
│ │ │ ├── schemas/index.yaml
│ │ │ └── openapi.yaml
│ │ └── swagger.ts
│ ├── infrastructure/
│ │ ├── config/
│ │ ├── logger/
│ │ ├── cache/
│ │ │ ├── CacheService.ts
│ │ │ ├── HtmlCacheManager.ts
│ │ │ └── RedisClient.ts
│ │ └── persistence/
│ │ ├── PlayerIdRepository.ts
│ │ ├── SqlitePlayerIdRepository.ts
│ │ └── PostgresPlayerIdRepository.ts
│ ├── modules/
│ │ ├── career/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ └── parser/
│ │ ├── games/
│ │ └── heroes/
│ ├── shared/
│ │ ├── errors/
│ │ ├── middlewares/
│ │ └── utils/
│ ├── types/
│ └── data/
│ ├── heroes.json
│ └── typeToCategoryIdMap.json
├── tests/
│ ├── fixtures/
│ ├── helpers/
│ ├── integration/
│ ├── unit/
│ └── setup.ts
├── .env.example
├── .nvmrc
├── package.json
├── tsconfig.json
└── vitest.config.ts
本项目基于 MIT License 开源。
欢迎通过 Issue 与 Pull Request 参与改进:
- Issue:报告 Bug、提出使用问题或改进建议。
- Pull Request:提交代码前请确保:
pnpm typecheck通过pnpm test全部通过- 遵循现有代码风格与目录结构
由于本项目依赖抓取 Overwatch 官方公开页面,页面结构可能随官网更新变化。如遇解析失效,欢迎提交 Issue 并附上对应的 BattleTag 与错误信息。
本项目为个人开发的非官方开源项目,与 Blizzard Entertainment, Inc.(暴雪娱乐)没有任何关联,也未获得其授权、认可或赞助。
- 本项目不隶属于暴雪娱乐,也不是暴雪的官方产品或服务。
- 项目数据均来自 Overwatch 官方公开的 Career 页面,仅通过公开页面抓取与解析获取,未使用任何官方私有接口,也不存储或分发任何暴雪的受版权保护内容。
Overwatch(守望先锋)、Blizzard(暴雪)及相关名称、标识、商标均为 Blizzard Entertainment, Inc. 的财产,其所有权归暴雪娱乐所有。本项目中出现的上述名称仅用于说明用途。- 本项目按「现状」提供,不对数据的准确性、完整性、时效性或可用性作任何保证。因使用本项目所产生的任何后果由使用者自行承担。
- 使用者应自行遵守 Blizzard 相关服务条款及适用法律法规,合理使用本项目,避免对官方服务造成不当负担。