Skip to main content
Glama

danxiapi

复旦大学校园 + 论坛 API 框架 —— 从 DanXI-Dev/DanXi 抽取已验证的接口,为**智能体(LLM Function Calling / MCP)**与二次开发提供 易调用、易扩展的 Python 接口。

四种形态,同一个内核:

形态

安装

入口

Python SDK(核心)

pip install danxiapi

DanXiClient / AsyncDanXiClient

CLI

pip install danxiapi[cli]

danxi

HTTP 网关

pip install danxiapi[gateway]

danxi serve

MCP Server

pip install danxiapi[mcp]

danxi mcp

全要:pip install "danxiapi[all]"

能力一览

  • 统一认证:UIS 传统登录 / Neo 新一代认证(RSA)/ 树洞 JWT,自动探测 2FA 与验证码

  • WebVPN(aTrust 2.0)login_webvpn()vpn.fudan.edu.cn 的 OAuth2 授权码流程, 复用同一套 Neo 认证——旧的 AES-CFB 地址改写方案已随 webvpn.fudan.edu.cn 退役

  • 树洞(FDU Hole):分区、树洞、楼层、搜索、收藏/订阅、消息、AI 摘要

  • 教务:学期、课表、成绩、GPA(两步 join)、考试安排、学生身份

  • 校园生活:宿舍电费、一卡通余额与流水、食堂拥挤度、图书馆拥挤度、教务公告

  • 课评(DanKe)、eHall 身份、研究生课表/成绩(优先级较低)

  • 优雅退化:图书馆 / 空教室 / WebVPN 等只在校园网内应答的能力,会在发请求前 探测可达性,不可达时抛 FeatureUnavailable,绝不 hang、绝不返回假数据

  • 二次验证不绕过my.fudan.edu.cn 的食堂拥挤度等接口服务端要求增强认证。 SDK 会抛出 TwoFactorRequired 并附 manual_login_url——给出可手工登录的链接, 而不是假装返回空列表,也不是尝试程序化破解

Related MCP server: hdu-ics-mcp-server

快速开始

from danxiapi import DanXiClient

with DanXiClient() as dx:
    dx.login_uis()                     # 从 .env 读 USERID / PASSWORD
    dx.login_forum()                   # 默认 <学号>@m.fudan.edu.cn

    for course in dx.get_timetable():  # 本学期课表
        print(course.name, course.teacher, course.classroom)

    print(dx.get_gpa().overall_gpa)

    for floor in dx.search_floors("食堂"):
        print(floor.content[:80])

异步版本接口完全一致:

async with AsyncDanXiClient() as dx:
    await dx.login_uis()
    courses = await dx.get_timetable()

写操作安全:发帖 / 回复 / 点赞 / 举报全部默认 dry_run=True。 必须显式传 dry_run=False 才会真正发送。

CLI

cp .env.example .env          # 填入学号与密码
danxi login --forum           # 登录 SSO(与树洞)
danxi whoami                  # 姓名 / 院系 / 专业 / 树洞状态
danxi timetable | grades | gpa | exams
danxi elec                    # 宿舍电费
danxi ecard balance | records # 一卡通余额 / 消费记录
danxi canteen                 # 食堂拥挤度(服务端要求 2FA,见下)
danxi library                 # 图书馆拥挤度(仅校园网)
danxi notices                 # 教务公告
danxi forum divisions | list | search
danxi config doctor           # 主机可达性矩阵 + 凭据诊断

所有命令支持 --json,输出可直接被脚本消费;列表输出带表格渲染。 根级选项 --verbose / -v 会附上上游 URL 与响应片段,方便排查改版问题 (注意它要写在子命令之前:danxi -v canteen)。

需要二次验证的接口

my.fudan.edu.cn 的食堂拥挤度与电费历史在服务端开启了增强认证,仅凭账号密码 无法获取。SDK 不会猜测、也不会返回空列表冒充成功,而是直接报错并给出链接:

╭── TwoFactorRequired (exit 11) ─────────────────────────╮
│ 服务要求增强认证(二次验证),无法仅凭账号密码登录……   │
│ 请在浏览器中打开下面的链接,完成验证码/二次验证后重试  │
│ https://my.fudan.edu.cn/simple_list/stqk               │
╰────────────────────────────────────────────────────────╯

这是预期行为:CLI 退出码 11,MCP 信封里是 {"ok": false, "error": {"type": "TwoFactorRequired", "manual_login_url": ...}}, 网关返回 403。在浏览器里完成一次该服务的登录后会话即生效。

只在校园网内可用的接口

图书馆拥挤度(mlibrary.fudan.edu.cn)与空教室(10.64.130.6)只对校园网应答。 SDK 在发请求之前并发探测这些主机:不可达时立即抛 FeatureUnavailable, 而不是让调用方卡在 socket 超时上。探测结果带缓存,danxi config doctor 可查看。

探测会兼容 ALL_PROXY=socks://... 环境:代理方案不合法时(未装 socksio) 自动改用直连重试一次,而不是把代理配置错误误报成「主机不可达」。

HTTP 网关

danxi serve --port 8000       # http://127.0.0.1:8000/docs

会话是不透明 idsecrets.token_urlsafe),凭据只存在内存/logout 与 TTL 过期即刻销毁。登录后用 Authorization: Bearer <session_id>HttpOnly cookie 调用其余接口:

SID=$(curl -s localhost:8000/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"...","password":"..."}' | jq -r .session_id)

curl -s localhost:8000/academic/gpa      -H "Authorization: Bearer $SID"
curl -s localhost:8000/campus/electricity -H "Authorization: Bearer $SID"
  • --read-only在路由注册层面禁掉论坛写接口(403 拒绝,而非 404), 公开演示时用

  • 限流(slowapi):/auth/login 与论坛写接口最严;--disable-rate-limit 可关

  • GET /system/features:报告当前网络探测到的可用能力(library / webvpn / empty_classroom

  • 会话 TTL:空闲 30 分钟 / 绝对 8 小时,均可通过启动参数覆盖

MCP Server

danxi mcp                     # stdio,凭据来自 USERID/PASSWORD 环境变量

挂到 Claude Code / Cursor 后,23 个工具直接可用:login_fudanget_timetableget_gradesget_gpaget_exam_arrangementget_electricityget_ecard_balanceget_ecard_recordsget_canteen_crowdednessget_library_crowdednesslist_noticeslist_divisionslist_holesget_holeget_floorssearch_floorsget_ai_summarylist_messagescreate_floordanke_searchdanke_reviews ……

约定:

  • 每个工具返回 {"ok": true, "data": ...}{"ok": false, "error": {"type": "TwoFactorRequired", "message": ..., "manual_login_url": ...}}失败会在协议层置 isError,宿主智能体不会 把「调用失败」当成「调用成功」。

  • TwoFactorRequired / CaptchaRequired 携带 manual_login_url:需要人工在 浏览器完成认证,不要盲目重试。get_canteen_crowdedness 未完成 2FA 时就是 这个信封,而不是空列表。

  • FeatureUnavailable(如 get_library_crowdedness 在校外)同样是错误信封: 「没有数据」和「不在校园网」对智能体是两回事。

  • 写工具默认不注册真实行为:需要 DX_MCP_ALLOW_WRITES=1 启动服务端, 并且调用时传 confirm=True,缺一不可。

  • get_ai_summary 是上游 LLM 生成的内容,可能幻觉,不可作为事实引用。

环境变量

变量

说明

USERID / PASSWORD

学号与 UIS 密码(等价于 DX_USERID / DX_PASSWORD

DX_FORUM_EMAIL

树洞登录邮箱,默认 <学号>@m.fudan.edu.cn

DX_LIVE

设为 1 才跑真网络测试

DX_LIVE_ALLOW_WRITES

设为 1 才允许真网络写测试

DX_MCP_ALLOW_WRITES

设为 1 才注册 MCP 写工具

DX_GATEWAY_READ_ONLY

设为 1 启动只读网关

DX_GATEWAY_ADMIN_KEY

守卫 /system/debug 的密钥;不设则该路由不注册

设计要点

  • 一次实现、同步异步双开:所有请求逻辑(cookie / 重定向 / 登录队列 / token 刷新) 写成同步的 httpx.BaseTransport,同时挂到 httpx.Clienthttpx.AsyncClient

  • 手动跟随重定向:SSO ticket 只能在中途拦截,自动重定向会丢 cookie

  • cookie epoch 守卫:并发登录时的旧 Set-Cookie 不会覆盖新会话 (对齐 DanXi issue #701 的修复)

  • 结构化数据:全部 pydantic v2 模型,抓取型模型带 raw 逃生口与解析容错; 一卡通流水按表头解析而非按列号切片,复旦改列序时会变成解析失败而不是 静默读错金额

  • 日志脱敏Authorization / cookie / 密码一律不打明文

  • 核心包零依赖适配层import danxiapi 不会传递引入 typer / fastapi / mcp (有单测在子进程里屏蔽这些模块强制保证)

测试

make test            # 离线单测 + 集成(零网络,默认)
make test-live       # 需 DX_LIVE=1 与 .env 凭据

三层标记,成本递增:

  • unit(离线):纯逻辑 —— RSA 往返、aTrust OAuth2 授权码链路、cookie epoch 竞态、 重定向 walker、pydantic 解析、MCP 信封约定、可达性探测的代理降级

  • integration(离线):respx 在 transport 层打桩,跑完整的 SessionEngine → transport → 解析链路

  • live(显式开启):真网络;写操作还要 DX_LIVE_ALLOW_WRITES=1

离线测试在 conftest.py 层面 patch 掉 httpx.Client.send,对 *.fduhole.com 的非 GET 请求直接抛异常 —— 结构上不可能从单测误发真实论坛内容。 tests/golden/ 钉死抓取契约:复旦改版导致解析漂移时会构建失败,而不是静默返回 []

许可证

GPL-3.0-only,与 DanXi 上游保持一致。见 LICENSE

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables LLM interaction with the Macau University of Science and Technology (M.U.S.T.) campus system, including automated login to Wemust and Moodle, retrieving class schedules, checking assignments and deadlines, downloading course materials, and managing course content.
    7
    3
    MIT
  • F
    license
    B
    quality
    C
    maintenance
    Enables querying of Hangzhou Dianzi University course schedules, exams, and campus events by accessing the HDUHelp ICS calendar subscription. Supports getting today's and upcoming events, as well as keyword search.
    3
    -
  • F
    license
    A
    quality
    C
    maintenance
    Enables interaction with Zhejiang University's learning platform (学在浙大 / 智云课堂) via MCP tools, allowing natural language commands to check todos, view schedules, fetch lecture transcripts, and submit homework.
    7
    3
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to search and retrieve Fudan University's Tree Hole community posts, course reviews, and campus discussions, including browsing tags and divisions, from off campus via WebVPN, and to summarize findings through natural language.
    1
    GPL 3.0