58 个接口,按 auth/crawler/creator/data/monitor/settings 分组,逐条列出方法、路径、 是否需要登录、说明、参数(含类型/必填/默认)、请求体 schema;附录展开请求体的字段。 **生成的,不是手写的** —— 手写的接口文档从改代码那天起就开始腐烂,而且烂得无声无息。 `docs/gen_api_doc.py` 只读 app 对象,不连库不起服务。 两处值得说的: * 鉴权**不能从 schema 里读** —— require_auth 是普通依赖不是 security scheme,不会进 OpenAPI 的 security 字段。所以那份「哪些路径免登录」的名单是照着 include_router 核的,而且 auth 那一组不能一刀切(/me 和 /password 各自另有保护)。 * 生成完**顺手验一遍表格**:参数类型里的 `integer | null` 到处是,一个没转义的竖线 就会把整张表切歪,而 markdown 不报错、只是安静地多一格。验过这个检查确实会拦。 接口的响应没有结构可列 —— 它们返回普通 dict,没声明 response_model。
14 KiB
14 KiB
API 接口清单
从 FastAPI 自己的 OpenAPI schema 生成的,不是手写的 —— 手写的接口文档从改代码那天起就开始腐烂,而且烂得无声无息。
重新生成:
./.venv/Scripts/python.exe docs/gen_api_doc.py
通用约定
| 前缀 | 所有接口都在 /api 下(WebSocket 是 /api/ws/...) |
| 鉴权 | Cookie 优先,Bearer 次之:token_from_request() 先读会话 Cookie,读不到再读 Authorization: Bearer <token>。浏览器用 Cookie,脚本用 Bearer |
| 会话怎么来 | POST /api/auth/login(密码),响应种下会话 Cookie;有效期由服务端 resolve_session() 判定 |
| 错误形状 | FastAPI 默认的 {"detail": "..."};401 是登录失效 |
没有 /docs |
特意关掉的:/docs、/redoc、/openapi.json 默认不需要登录,等于把整份接口地图连同「Try it out」一起送出去。要看交互式的,得挂在鉴权后面 |
| WebSocket | GET /api/ws/logs(升级为 ws)—— 实时日志流。不在这里的清单里:OpenAPI 描述不了 WebSocket。它自己用 require_ws_auth 校验会话 Cookie |
目录
认证
这一组没有统一挂 require_auth(登录不能要求先登录),所以逐个标。
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
POST |
/api/auth/login |
— | Login | LoginPayload | |
POST |
/api/auth/logout |
— | Logout | ||
GET |
/api/auth/me |
✓ | Identity probe. The SPA treats a 401 here as "show the login page". | ||
POST |
/api/auth/password |
✓ | Change the password and log every device out. | ChangePasswordPayload |
采集
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
GET |
/api/crawler/logs |
✓ | Get recent logs | limit(query integer 可选=100) |
|
POST |
/api/crawler/start |
✓ | Start crawler task. | CrawlerStartRequest | |
GET |
/api/crawler/status |
✓ | Get crawler status | ||
POST |
/api/crawler/stop |
✓ | Stop crawler task |
运营(博主账号)
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
GET |
/api/creator/accounts |
✓ | 账号列表。不含 cookie,只给 has_cookie。 |
||
DELETE |
/api/creator/accounts/{account_id} |
✓ | Delete Account | account_id(path integer 必填) |
|
GET |
/api/creator/accounts/{account_id} |
✓ | Get Account Detail | account_id(path integer 必填) |
|
POST |
/api/creator/accounts/{account_id}/check |
✓ | 重测登录态与数据权限。 | account_id(path integer 必填) |
|
POST |
/api/creator/accounts/{account_id}/sync |
✓ | 拉取作品数据。 | account_id(path integer 必填)days(query integer 可选=90) |
|
DELETE |
/api/creator/login |
✓ | Cancel Login | ||
GET |
/api/creator/login |
✓ | 轮询扫码结果;一旦成功就把账号落库并返回它。 | ||
POST |
/api/creator/login |
✓ | Start Login |
数据
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
GET |
/api/data/download/{file_path} |
✓ | Download file | file_path(path string 必填) |
|
GET |
/api/data/files |
✓ | Get data file list | platform(query string | null 可选)file_type(query string | null 可选) |
|
GET |
/api/data/files/{file_path} |
✓ | Get file content or preview | file_path(path string 必填)preview(query boolean 可选=True)limit(query integer 可选=100) |
|
GET |
/api/data/stats |
✓ | Get data statistics |
监控
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
GET |
/api/monitor/comment-notes |
✓ | Works that have comments, newest first, with counts. | task_id(query integer | null 可选)platform(query string | null 可选) |
|
GET |
/api/monitor/comments |
✓ | Comments, each carrying the work it belongs to. | task_id(query integer | null 可选)note_id(query string | null 可选)group_by(query string | null 可选)limit(query integer 可选=200)platform(query string | null 可选) |
|
DELETE |
/api/monitor/cookie |
✓ | Clear Cookie Endpoint | platform(query string 可选='xhs') |
|
GET |
/api/monitor/cookie |
✓ | Cookie health only -- deliberately never returns the cookie value. | platform(query string 可选='xhs') |
|
POST |
/api/monitor/cookie |
✓ | Set Cookie Endpoint | platform(query string 可选='xhs') |
CookiePayload |
GET |
/api/monitor/covers/{note_id} |
✓ | 作品封面,从本地缓存读。 | note_id(path string 必填) |
|
PUT |
/api/monitor/creators/{creator_hash} |
✓ | 给博主起个备注(界面上的「备注」)。 | creator_hash(path string 必填)platform(query string 可选='xhs') |
CreatorAliasPayload |
GET |
/api/monitor/events |
✓ | List Events | task_id(query integer | null 可选)type(query string | null 可选)since_id(query integer | null 可选)limit(query integer 可选=200)platform(query string | null 可选) |
|
POST |
/api/monitor/events/read |
✓ | Mark Events Read | task_id(query integer | null 可选) |
|
GET |
/api/monitor/export |
✓ | Download collected data as CSV or Excel. | kind(query string 必填)task_id(query integer[] | null 可选)note_id(query string | null 可选)start_date(query string | null 可选)end_date(query string | null 可选)days(query integer 可选=7)format(query string 可选='csv')platform(query string | null 可选) |
|
DELETE |
/api/monitor/login/qr |
✓ | Drop our tab and stop polling. | ||
GET |
/api/monitor/login/qr |
✓ | Poll the live session: waiting -> success / expired / error. | ||
POST |
/api/monitor/login/qr |
✓ | Open the login page in the CDP browser and return its QR code. | platform(query string 可选='xhs') |
|
GET |
/api/monitor/login/state |
✓ | Ask the browser itself whether it is signed in. | force(query boolean 可选=False) |
|
GET |
/api/monitor/notes |
✓ | List Notes | task_id(query integer | null 可选)only_new(query boolean 可选=False)limit(query integer 可选=200)platform(query string | null 可选)tag_id(query integer[] | null 可选) |
|
PUT |
/api/monitor/notes/{note_id} |
✓ | 给作品起个备注。 | note_id(path string 必填)platform(query string 可选='xhs') |
NoteAliasPayload |
GET |
/api/monitor/notes/{note_id}/series |
✓ | Metric time series for a single note. | note_id(path string 必填)task_id(query integer | null 可选) |
|
PUT |
/api/monitor/notes/{note_id}/tags |
✓ | 把一条作品的标签整体替换成这一组(空列表 = 全摘掉)。 | note_id(path string 必填)platform(query string 可选='xhs') |
NoteTagsPayload |
GET |
/api/monitor/overview |
✓ | Headline numbers for the dashboard tiles, scoped to one platform. | platform(query string | null 可选) |
|
GET |
/api/monitor/report |
✓ | Daily new-content counts and interaction deltas for the selected tasks. | task_id(query integer[] | null 可选)start_date(query string | null 可选)end_date(query string | null 可选)days(query integer 可选=7)platform(query string | null 可选) |
|
GET |
/api/monitor/tags |
✓ | 标签词表 + 各自被用在多少条作品上(删之前能看清代价)。 | ||
POST |
/api/monitor/tags |
✓ | Create Tag | TagPayload | |
DELETE |
/api/monitor/tags/{tag_id} |
✓ | 删标签,连同它在所有作品上的贴纸。 | tag_id(path integer 必填) |
|
PUT |
/api/monitor/tags/{tag_id} |
✓ | Update Tag | tag_id(path integer 必填) |
TagPayload |
GET |
/api/monitor/tasks |
✓ | List Tasks | platform(query string | null 可选) |
|
POST |
/api/monitor/tasks |
✓ | Create Task | MonitorTaskCreate | |
DELETE |
/api/monitor/tasks/{task_id} |
✓ | Delete Task | task_id(path integer 必填) |
|
PATCH |
/api/monitor/tasks/{task_id} |
✓ | Update Task | task_id(path integer 必填) |
MonitorTaskUpdate |
POST |
/api/monitor/tasks/{task_id}/run |
✓ | Queue a run immediately and return; the crawl itself takes minutes. | task_id(path integer 必填) |
|
GET |
/api/monitor/tasks/{task_id}/runs |
✓ | List Runs | task_id(path integer 必填)limit(query integer 可选=50) |
|
GET |
/api/monitor/upstream |
✓ | 最近一次上游检查的结果。 | ||
POST |
/api/monitor/upstream/check |
✓ | 立刻检查一次上游仓库,并把结果写回缓存。 | ||
DELETE |
/api/monitor/webhook |
✓ | Clear Webhook | ||
GET |
/api/monitor/webhook |
✓ | Get Webhook | ||
POST |
/api/monitor/webhook |
✓ | Set Webhook | WebhookPayload | |
POST |
/api/monitor/webhook/test |
✓ | Send a test message so the user can verify the robot works before relying on it. | WebhookTestPayload |
设置
| 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 |
|---|---|---|---|---|---|
GET |
/api/settings |
✓ | Settings for one platform, plus the system-wide ones. | platform(query string 可选='xhs') |
|
PUT |
/api/settings |
✓ | Partial update: only the keys present in the body are written. | platform(query string 可选='xhs') |
SettingsUpdatePayload |
请求体结构
ChangePasswordPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
current |
string | ✓ | ||
new |
string | ✓ |
CookiePayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
cookie |
string | ✓ |
CrawlerStartRequest
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
platform |
PlatformEnum | ✓ | ||
login_type |
LoginTypeEnum | 'qrcode' | ||
crawler_type |
CrawlerTypeEnum | 'search' | ||
keywords |
string | '' | ||
specified_ids |
string | '' | ||
creator_ids |
string | '' | ||
start_page |
integer | 1 | ||
enable_comments |
boolean | True | ||
enable_sub_comments |
boolean | False | ||
enable_media |
boolean | False | ||
save_option |
SaveDataOptionEnum | 'jsonl' | ||
cookies |
string | '' | ||
headless |
boolean | False | ||
max_notes_count |
integer | null | |||
max_comments_count |
integer | null | |||
save_data_path |
string | null | |||
enable_cdp_mode |
boolean | null | |||
inject_all_cookies |
boolean | null | |||
save_login_state |
boolean | null | |||
cookies_file |
string | null | |||
max_concurrency_num |
integer | null | |||
crawler_max_sleep_sec |
integer | null | |||
enable_ip_proxy |
boolean | null | |||
ip_proxy_pool_count |
integer | null | |||
ip_proxy_provider_name |
string | null | |||
static_proxy_url |
string | null |
CreatorAliasPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
alias |
string | '' |
LoginPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
password |
string | ✓ |
MonitorTaskCreate
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name |
string | ✓ | ||
platform |
string | 'xhs' | ||
mode |
string | ✓ | ||
interval_minutes |
integer | null | |||
schedule_mode |
string | 'interval' | ||
schedule_hours |
integer[] | |||
schedule_days |
integer[] | |||
schedule_minute |
integer | 0 | ||
max_notes_count |
integer | null | |||
enable_comments |
boolean | True | ||
max_comments_count |
integer | null | |||
run_timeout_seconds |
integer | 3600 | ||
enabled |
boolean | True | ||
notify_enabled |
boolean | False | ||
notify_failures |
boolean | True | ||
targets |
string[] | ✓ |
MonitorTaskUpdate
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name |
string | null | |||
enabled |
boolean | null | |||
interval_minutes |
integer | null | |||
schedule_mode |
string | null | |||
schedule_hours |
integer[] | null | |||
schedule_days |
integer[] | null | |||
schedule_minute |
integer | null | |||
max_notes_count |
integer | null | |||
enable_comments |
boolean | null | |||
max_comments_count |
integer | null | |||
run_timeout_seconds |
integer | null | |||
notify_enabled |
boolean | null | |||
notify_failures |
boolean | null | |||
targets |
string[] | null |
NoteAliasPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
alias |
string | '' |
NoteTagsPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
tag_ids |
integer[] |
SettingsUpdatePayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|
TagPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name |
string | ✓ | ||
color |
string | '' |
WebhookPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
url |
string | '' | 企业微信机器人 Webhook 地址,留空表示停用 |
WebhookTestPayload
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
url |
string | null | 不传则使用已保存的地址 |
响应没有结构可列。 这些接口返回的是普通 dict,没有声明
response_model,所以 OpenAPI 里没有响应的 shape。要看响应就调一次,或者读对应的service.py。