D2L Brightspace命令行工具:AI智能体集成与自动化学习管理
1. 项目概述:一个为AI智能体设计的D2L Brightspace只读命令行工具
如果你是一名学生,同时又是开发者,或者你正在尝试用AI助手(比如Claude Code、Cursor的AI)来提升学习效率,那你肯定对在D2L Brightspace(国内常称为“学习通”的国际版)里反复点击、翻找课程资料、成绩和作业截止日期的过程感到厌倦。 d2l-cli 这个项目,就是为解决这个痛点而生的。它本质上是一个Python编写的命令行工具,核心功能是帮你把D2L平台上的所有只读信息——成绩、作业、课程内容、大纲、讨论区——统统拉到本地,并以结构化的方式(表格、JSON、Markdown)呈现出来。但它的真正精髓在于,它是 专为AI智能体(AI Agent)设计的 。这意味着,你不用再手动敲命令,而是可以直接对你的AI助手说:“帮我看看这周数据结构的作业是什么?”或者“我这学期微积分的成绩趋势怎么样?”,AI会理解你的意图,并自动调用 d2l-cli 来获取答案。
我最初接触这个工具,是因为受够了在多个课程页面间切换查看截止日期。手动整理太耗时,而现有的浏览器插件要么功能不全,要么不适合自动化。 d2l-cli 吸引我的地方在于它的“API化”思路:它通过逆向工程D2L的官方API(尽管是只读的),提供了一个干净、一致的命令行接口。这对于希望将学习数据接入自己工作流(比如生成学习周报、自动备份资料)的开发者来说,是一个极佳的起点。更重要的是,它的输出格式(特别是 --md 和 --json )是天然为AI对话设计的,使得AI助手能轻易地解析信息并生成对人类友好的总结。
2. 核心设计思路:为什么是“只读CLI”加“AI Agent就绪”?
2.1 定位解析:解决信息获取的“最后一公里”问题
D2L Brightspace作为一个功能完备的LMS(学习管理系统),其前端界面是为人类交互设计的,而非机器。虽然它提供官方API,但直接使用其REST API对于普通学生甚至开发者来说,门槛依然不低:需要处理OAuth2认证、理解复杂的API端点结构、解析嵌套的JSON响应。 d2l-cli 所做的,就是封装了所有这些复杂性。
它的设计定位非常清晰:
- 只读(Read-Only) :这是一个关键的安全与伦理设计。工具明确声明不执行任何POST、PUT、DELETE操作。这意味着它无法替你提交作业、发布帖子或修改任何数据,完全避免了误操作或学术不端行为的风险。从技术实现上看,它的所有请求都严格限定为HTTP GET方法。
- 命令行优先(CLI-First) :CLI是自动化的基石。通过命令行,你可以轻松地将它集成到Shell脚本、定时任务(Cron)或其他程序中。例如,你可以写一个脚本,每天上午8点运行
d2l due --days 1,将当天截止的作业列表发送到你的Telegram或邮箱。 - AI Agent就绪(AI-Agent-Ready) :这是项目最具前瞻性的部分。它不仅仅是提供了一个CLI,还包含了完整的AI Agent集成指南(
AGENTS.md)和针对特定Agent(如Claude Code)的技能文件(Skill File)。这相当于为AI助手预装了一个“D2L信息查询”的插件,让AI具备了直接与你的学习数据对话的能力。
2.2 技术选型与架构考量
项目采用Python实现,这是一个明智的选择。Python拥有丰富的网络请求( requests , httpx )、HTML解析( beautifulsoup4 )和浏览器自动化( playwright )库生态,非常适合完成此类“网页抓取+API调用”的混合任务。
其架构大致可以分为三层:
- 认证层 :处理最棘手的D2L Bearer Token(JWT)获取。它提供了两种方式:基于Playwright的浏览器自动化登录(模拟用户登录流程截取Token)和手动配置Token。前者用户体验好,后者更适合无头服务器环境。
- API客户端层 :封装了对D2L Brightspace REST API的各种调用。这里需要仔细研究网络请求,找到正确的API端点(如
/d2l/api/lp/(version)/enrollments/myenrollments/用于获取课程列表)。项目代码需要处理分页、错误重试、速率限制等细节。 - 命令层 :使用像
click或argparse这样的库来构建命令行界面,将不同的功能(grades,assignments,download)映射为子命令,并处理参数解析、输出格式化(文本表格、JSON、Markdown)。
对于SimpleSyllabus(一个常见的课程大纲插件)的集成,项目采用了另一种思路。因为大纲数据可能来自独立的第三方服务,所以它没有直接使用D2L API,而是通过分析SimpleSyllabus网站自身的API(通过浏览器开发者工具捕获),实现了直接的数据获取。这体现了开发者解决实际问题的灵活性和对细节的把握。
3. 从零开始:环境配置与初次认证实战
3.1 基础环境搭建
假设你使用的是macOS或Linux系统(Windows用户请将 bin 替换为 Scripts ),我们从头开始。
# 1. 克隆仓库
git clone https://github.com/Aaryan-Kapoor/d2l-cli.git
cd d2l-cli
# 2. 创建并激活虚拟环境(强烈推荐,避免污染全局Python环境)
python -m venv .venv
source .venv/bin/activate # 激活后,命令行提示符前通常会出现 (.venv)
# 3. 安装核心依赖
pip install -e .
pip install -e . 中的 -e 代表“可编辑模式”安装。这会将当前目录以“开发模式”链接到Python的site-packages中。这样,你后续在 src/ 目录下修改任何代码,都会立即生效,无需重新安装。
注意 :项目要求Python 3.10+。请务必使用
python --version确认版本。如果系统默认版本过低,你可能需要先安装更高版本的Python,或者使用python3命令。
3.2 关键配置详解
安装完成后,不要急着运行。首先需要配置你的学校信息。核心配置文件在 src/d2l/config.py 。
# 打开并编辑这个文件
LMS_HOST = "https://your-school.view.usg.edu" # 你的D2L Brightspace登录地址
TENANT_ID = "your-tenant-id-here" # 租户ID,需要从浏览器中获取
-
LMS_HOST:这个就是你的学校D2L主页的URL。通常以https://[学校名].brightspace.com或类似形式出现。 千万不要带结尾的斜杠 。 -
TENANT_ID:这是D2L多租户架构的标识。获取它需要一点技巧:- 登录你的D2L网站。
- 打开浏览器开发者工具(F12),切换到“网络”(Network)标签页。
- 刷新页面,在网络请求列表中,找到一个指向
*.api.brightspace.com域名的请求。 - 点击该请求,在“标头”(Headers)部分,找到请求URL。你会在URL路径中看到类似
.../versions/...?tenantId=123456的参数,或者直接在请求头里找。TENANT_ID就是那个数字ID。如果找不到,也可以尝试在页面HTML源码中搜索tenantId。
如果你的学校使用了SimpleSyllabus,还需要配置 src/d2l/commands/syllabus.py 中的URL:
SYLLABUS_SEARCH_URL = "https://your-school.simplesyllabus.com/api2/syllabus-search"
SYLLABUS_FULL_URL = "https://your-school.simplesyllabus.com/api2/doc-full-page-get"
将 your-school 替换为你的学校子域名。
3.3 认证实战:两种获取Token的方法
D2L API使用Bearer Token(JWT)进行认证,这个Token大约每小时过期一次。
方法A:浏览器自动捕获(推荐给个人用户)
首先,需要安装额外的登录支持包和浏览器驱动。
pip install -e ".[login]" # 安装playwright等依赖
playwright install chromium # 安装Chromium浏览器,用于无头操作
然后运行登录命令:
d2l login
这个命令会:
- 启动一个Chromium浏览器实例。
- 导航到你配置的
LMS_HOST。 - 模拟登录流程(你需要手动输入用户名密码,完成学校的SSO认证,如Duo Push等)。
- 登录成功后,工具会监控浏览器与D2L API的通信,自动捕获
Authorization: Bearer ...这个请求头,并将Token及相关信息(过期时间、用户ID等)保存到~/.d2l/token.json文件中。
实操心得 :第一次运行
d2l login可能会因为浏览器弹窗或学校复杂的SSO流程而失败。确保你的系统有图形界面。如果遇到问题,可以尝试d2l login --headless,它会在后台无界面模式下运行,但前提是你之前已经成功登录过且浏览器保存了会话Cookie。
方法B:手动获取Token(适用于服务器或无GUI环境)
- 在已登录D2L的浏览器中,按F12打开开发者工具。
- 进入“网络”标签,筛选
XHR或Fetch请求。 - 刷新D2L页面,在请求列表中找到任意一个指向
https://[你的学校].api.brightspace.com/...的请求。 - 点击该请求,在右侧“标头”部分,找到“请求标头”下的
Authorization。其值类似Bearer eyJhbGciOiJ...(一串很长的字符串)。 - 复制整个
Bearer后面的Token字符串(不包括单词Bearer和空格)。 - 在终端中,创建目录和文件:
然后编辑mkdir -p ~/.d2l~/.d2l/token.json,填入以下内容(需要计算过期时间戳exp,通常捕获时间captured_at加3600秒即可):
你可以使用 jwt.io 解码Token(不要泄露给不可信的网站),来获取{ "token": "你复制的很长很长的JWT Token", "exp": 1741234567, "sub": "你的用户ID(可从Token解码或API获取)", "tenant": "你的TENANT_ID", "captured_at": 1741230967 }sub(用户ID)和exp(过期时间戳)字段。captured_at可以设为当前时间的时间戳。
验证Token : 配置和认证完成后,运行以下命令测试:
d2l token # 查看Token状态(本地检查,不调用API)
d2l whoami # 调用API获取当前用户信息,验证Token是否有效
如果 whoami 成功返回你的姓名和用户ID,恭喜你,最困难的一步已经完成了。
4. 核心命令深度使用与AI集成指南
4.1 课程与学术信息查询
安装配置好后,你就可以像使用普通命令行工具一样查询信息了。所有命令都支持模糊匹配课程名称。
# 1. 列出本学期所有课程
d2l courses
# 输出是一个清晰的表格,包含课程ID、名称、代码和学期。
# 2. 查看特定课程的成绩(例如课程名包含“data”)
d2l grades "data"
# 默认显示当前成绩项(作业、测验等)的分数和权重。
# 3. 使用 --final 标志查看计算后的课程总评成绩(如果老师已发布)
d2l grades "calculus" --final
# 4. 查看某门课的所有作业
d2l assignments "introduction to programming"
# 会列出作业名称、状态、截止日期、是否已提交等信息。
# 5. 查看所有课程的近期截止事项(默认未来7天)
d2l due
# 这是我最常用的命令之一,它能从所有课程中聚合出即将到期的作业和测验。
# 6. 查看已过期的任务
d2l overdue
# 7. 获取课程大纲(如果学校使用SimpleSyllabus)
d2l syllabus "physics 101"
# 这个命令非常有用,它能直接抓取完整的、格式化的课程大纲PDF或HTML,其中包含了评分政策、课程安排等关键信息。
4.2 内容管理与文件下载
除了查看信息, d2l-cli 还能帮你把资料“搬”下来。
# 1. 查看课程的内容模块结构
d2l content "web development" --toc
# `--toc` 参数会以树状图形式展示模块和主题,让你对课程结构一目了然。
# 2. 下载特定作业的附件(比如老师提供的starter code)
d2l download "data structures" "assignment 5" -o ./ds_a5
# 这个命令会解析指定作业,找到所有附件(ZIP, PDF等)并下载到 `./ds_a5` 目录。
# 3. 下载整个内容模块的文件
d2l download-content "calculus" "week 3 lectures" -o ./calc_notes
# 这会遍历“week 3 lectures”模块下的所有主题,下载其中的PPT、PDF、视频链接等资源。
注意事项 :下载功能依赖于D2L内容页面的HTML结构。如果你们学校的D2L界面经过深度定制,下载链接的提取可能会失败。此时需要查看
src/d2l/commands/download.py中的解析逻辑,可能需要根据实际情况调整CSS选择器或正则表达式。
4.3 输出格式:为人类和机器准备的三种视图
这是 d2l-cli 设计上的一个亮点,它提供了三种输出格式以适应不同场景。
| 格式 | 命令示例 | 适用场景 | 特点 |
|---|---|---|---|
| 默认表格 | d2l grades | 人类在终端快速阅读 | 对齐的、彩色的(如果终端支持)文本表格,直观美观。 |
| JSON | d2l --json grades | 脚本处理、二次开发 | 结构化的数据,方便用 jq 过滤或用Python的 json 库解析。例如:`d2l --json due |
| Markdown | d2l --md grades | AI Agent交互 、生成报告 | 纯文本Markdown格式,包含完整上下文(如课程ID、日期ISO格式)。AI最容易理解和处理这种格式。 |
为什么 --md 格式对AI如此重要? 当你问AI:“我这学期成绩怎么样?”AI需要调用 d2l-cli 。如果返回的是JSON,AI需要先解析数据结构再组织语言。如果返回的是纯文本表格,AI可能难以精确提取字段。而 --md 格式是两者的折中:它既是人类可读的(有标题、列表),又保留了机器可读的结构化信息(比如用 **Course:** 明确标识字段),极大降低了AI的理解和转换成本。项目中的 AGENTS.md 文件就是教AI如何正确使用这些命令和解析 --md 输出的“说明书”。
4.4 与AI智能体深度集成:以Claude Code为例
这才是 d2l-cli 的“杀手级”应用场景。我们以目前非常流行的Claude Code(集成在Cursor、Windsurf等编辑器中的Claude)为例。
步骤1:为AI准备环境 AI智能体(Agent)需要在它自己的运行时环境中能访问到 d2l 命令。最简单的方法就是在你启动AI对话的项目根目录下,也安装一份 d2l-cli 。
# 在你的项目目录下
cd /path/to/your/workspace
# 假设d2l-cli仓库在隔壁目录
pip install -e ../d2l-cli
# 确保token已配置(~/.d2l/token.json 已存在且有效)
步骤2:让AI“学会”使用这个工具 d2l-cli 仓库根目录下的 AGENTS.md 文件,就是写给AI看的完整工具文档。你需要让AI知道这个文件的存在。
- 在Claude Code中 :你可以直接上传
AGENTS.md文件,或者将它的内容粘贴到对话中,并告诉Claude:“这是你用来查询我D2L学习信息的工具文档,请根据它来回答我的问题。” - 更优雅的方式 :对于Claude Code,项目还提供了
.claude/skills/d2l/SKILL.md文件。你可以将这个技能文件复制到你的项目目录下的.claude/skills/文件夹中。Claude Code会自动加载这个技能,使其成为一个可用的“工具”。
步骤3:开始自然语言对话 完成以上步骤后,你就可以像和助手说话一样提问了:
- “ 帮我看看下周有哪些作业要交。 ”
- AI会理解意图,在后台执行
d2l due --days 7 --md,解析返回的Markdown,然后生成一个清晰的列表告诉你。
- AI会理解意图,在后台执行
- “ 我在‘数据科学与机器学习’这门课上的当前成绩是多少?把每次作业的分数都列出来。 ”
- AI会执行
d2l --md grades "data science",然后从输出中提取表格,并可能帮你计算一下当前加权平均分。
- AI会执行
- “ 把‘计算机视觉’课程第三周的所有讲义下载到当前目录的
cv_week3文件夹里。 ”- AI会执行
d2l download-content "computer vision" "week 3" -o ./cv_week3并告诉你下载结果。
- AI会执行
步骤4:进阶用法——生成学习周报 你可以给AI更复杂的任务: “ 基于我过去一周的D2L活动,生成一份学习周报。包括:1) 新发布的公告,2) 已提交和待提交的作业,3) 所有课程的最新成绩变化。用Markdown格式输出,并给出下周的学习建议。 ” AI可能会组合调用多个命令:
d2l --json news --since 7
d2l --json assignments --all
d2l --json grades --all
然后综合分析这些JSON数据,生成一份结构化的周报。
4.5 无头服务器与自动化部署
如果你想在云服务器或树莓派上运行一个定时查询任务,就需要“无头”(Headless)环境。
- 初始Token获取 :你仍需在一个有图形界面的机器上(比如你的笔记本电脑)运行一次
d2l login。这会生成~/.d2l/token.json和~/.d2l/browser_context(Playwright的浏览器会话数据)。 - 迁移数据 :将整个
~/.d2l/目录打包复制到你的服务器上。 - 设置定时刷新 :Token一小时过期,但浏览器会话Cookie可能持续数天甚至数周。我们可以设置一个Cron任务,定期用
--headless模式重新登录(利用已保存的Cookie,无需再次输入密码)。# 编辑crontab: crontab -e # 每隔45分钟运行一次登录命令(在虚拟环境中) */45 * * * * cd /path/to/d2l-cli && /path/to/.venv/bin/d2l login --headless > /tmp/d2l-refresh.log 2>&1--headless模式会使用之前保存的浏览器上下文静默刷新Token。 - 定时任务示例 :每天早晨8点,查询当天截止的作业,并发送通知。
然后在Cron中添加:# 一个简单的Shell脚本 /home/user/check_due.sh #!/bin/bash source /path/to/d2l-cli/.venv/bin/activate OUTPUT=$(d2l due --days 1 --md) if [ -n "$OUTPUT" ]; then echo "$OUTPUT" | mail -s "今日D2L截止提醒" your-email@example.com # 或者调用Telegram/Bark的API发送到手机 fi0 8 * * * /bin/bash /home/user/check_due.sh
5. 常见问题排查与实战经验分享
即使按照指南操作,在实际部署和使用中,你仍可能会遇到一些问题。下面是我在深度使用过程中总结的一些典型问题和解决方案。
5.1 认证与登录失败
问题1: d2l login 打开浏览器后,页面卡在学校的SSO登录页,无法自动跳转/捕获Token。
- 原因 :学校的SSO流程(如使用Duo Mobile、Microsoft Entra ID)可能有额外的安全挑战(点击推送、输入验证码),Playwright脚本无法自动处理这些交互。
- 解决方案 :
- 使用
d2l login --headless试试。有时无头模式反而更稳定。 - 如果不行,退而求其次,采用 手动获取Token 的方法。虽然麻烦一次,但一劳永逸。
- 检查
config.py中的LMS_HOST是否正确。确保它是你实际登录的首页地址,而不是某个深层链接。
- 使用
问题2:Token频繁过期,即使刚获取不久。
- 原因 :D2L的JWT Token有效期通常是1小时,但可能因服务器配置而异。另外,如果你在多台设备上同时使用同一个账号,可能会使之前的Token失效。
- 解决方案 :
- 运行
d2l token检查Token的过期时间(exp)。确认是否真的过期。 - 实施上述的Cron自动刷新方案,确保服务器上的Token始终新鲜。
- 考虑编写一个简单的包装脚本,在执行任何
d2l命令前先检查Token有效期,如果临近过期(如剩余少于5分钟),则自动调用d2l login --headless刷新。
- 运行
5.2 命令执行报错或返回空数据
问题3:运行 d2l courses 或 d2l grades 返回空列表或404错误。
- 原因A:Tenant ID配置错误。 这是最常见的原因。API请求的URL中需要正确的租户ID。
- 排查 :运行
d2l whoami。如果失败,大概率是认证或Tenant ID问题。再次确认config.py中的TENANT_ID是否与浏览器捕获的一致。 - 原因B:API端点不匹配。 不同学校或不同版本的D2L,API路径可能略有差异。
- 排查 :打开浏览器开发者工具,在成功加载课程列表的页面,观察网络请求中真正的API调用地址。与
d2l-cli代码中(如src/d2l/api/courses.py)拼接的URL进行对比。你可能需要根据实际情况微调代码中的路径模板。
问题4: d2l syllabus 命令无法获取大纲,返回“Syllabus not found”或类似错误。
- 原因 :你的学校可能没有使用SimpleSyllabus,或者使用了但域名不同。
- 解决方案 :
- 手动访问一门课程的大纲页面。
- 打开开发者工具,搜索网络请求中包含
syllabus或simplesyllabus的API调用。 - 将找到的URL更新到
src/d2l/commands/syllabus.py的配置中。 - 如果学校根本不用SimpleSyllabus,那么这个功能就无法使用。你可以尝试查看
d2l content命令的输出,大纲有时会作为一个普通的HTML文件或PDF存在于课程内容模块中。
5.3 与AI智能体协作时的调试技巧
问题5:AI助手无法正确调用 d2l 命令,或解析输出有误。
- 原因 :AI没有获得正确的上下文或指令。
- 解决方案 :
- 明确指令 :在提问时,更明确地指示AI使用工具。例如:“请使用
d2l-cli工具,运行d2l --md due --days 3来获取我未来三天的截止任务,然后总结给我听。” - 提供技能文件 :确保
AGENTS.md或.claude/skills/d2l/SKILL.md的内容已被AI加载。对于Claude Code,你可以直接在对话中说:“我已为你安装了d2l-cli技能,请查阅你的技能列表并使用它。” - 检查输出格式 :如果AI解析混乱,尝试让AI使用
--json格式输出,然后你告诉AI:“你刚才返回的是JSON,请用自然语言解读一下其中的assignments数组。” 这可以帮助AI(和你)理解数据结构。
- 明确指令 :在提问时,更明确地指示AI使用工具。例如:“请使用
问题6:在自动化脚本中, d2l 命令的输出包含颜色代码或进度条,影响解析。
- 原因 :
d2l-cli在输出到终端时会使用颜色美化表格,但这些ANSI转义码在脚本中会成为干扰字符。 - 解决方案 :在命令中设置环境变量强制禁用颜色。
这样能确保输出是干净的文本或JSON。NO_COLOR=1 d2l courses --json # 或者 FORCE_COLOR=0 d2l courses --json
5.4 性能与扩展性考量
问题7: d2l dump 命令运行很慢,或者返回数据不全。
- 原因 :
dump命令会遍历你所有课程的大部分数据(成绩、作业、内容等),如果课程多、内容杂,API调用次数会剧增,导致速度慢。--shallow参数可以只获取摘要信息,加快速度。 - 建议 :
- 使用
--course参数指定单个课程进行深度dump。 - 使用
--since N参数只获取最近N小时内的更新。 - 考虑将全量dump作为低频后台任务(比如每周一次),而高频查询使用
due,news,updates等针对性命令。
- 使用
扩展思路 : d2l-cli 提供了一个强大的基础。你可以基于它构建自己的应用:
- 成绩追踪器 :定期运行
d2l --json grades --all,将JSON数据存入SQLite数据库,并绘制每门课的成绩变化曲线图。 - 资源归档机器人 :学期初,写个脚本遍历所有课程,用
d2l content --toc获取目录,然后自动调用d2l download-content把所有讲义、视频链接保存下来,并按课程-模块整理好。 - 个性化仪表盘 :将
d2l --json dump的数据喂给一个本地Web应用(比如用Flask或Streamlit),生成一个属于你自己的、干净简洁的学习仪表盘,摆脱D2L笨重的界面。
这个项目的价值在于它打通了“封闭的LMS系统”与“开放的个人自动化工具”之间的壁垒。它尊重系统的只读边界,同时又赋予了学生极大的信息掌控权和流程自动化能力。尤其是在AI智能体时代,它将自己变成了一个高效的“信息查询插件”,让AI真正成为了学习的得力助手,而不仅仅是编程的伙伴。
更多推荐



所有评论(0)