成绩导出这件事很适合被低估。页面上看起来只有几张表,真正想做成一个可靠脚本,却要处理登录状态、验证码或跳转、表格结构变化、缺考和缓考标记,以及最后导出的文件是否仍然能被人读懂。
gcc-cjcx 的公开仓库把它定位成教务系统成绩导出助手,后续提交又补了 GreasyFork 安装支持和安装说明。这个过程让我更愿意把它写成“重复流程的整理”,而不是“从此不用手抄”的夸张故事。脚本节省的是机械操作,不能替用户确认成绩是否属于正确学期。
解析时最重要的是保留原始上下文。课程名、学分、成绩、绩点和课程性质不能只靠表格列号硬编码,最好先识别表头,再对每一行做字段校验。页面结构改变时,脚本应该明确失败并给出原因,而不是导出一份看起来完整、实际列错位的 CSV。
登录信息也不能写进脚本或仓库。浏览器扩展可以复用当前会话,但需要让用户知道脚本访问了什么页面;命令行版本则应该使用安全的交互输入或已有登录态。自动化工具越方便,越要把权限范围写明白。
导出完成以后还要做一次反向检查:总课程数是否和页面显示一致,必修课和选修课是否被混在一起,空白成绩是否被当成零分,文件名是否包含足够的学期信息。一个简单的行数对比,就能挡住很多“脚本成功运行但结果不对”的问题。
安装指南的存在也很重要。把脚本放进仓库只能让熟悉开发的人使用,GreasyFork 页面、版本号和更新说明才让普通使用者知道怎样安装、怎样回滚。每次页面变化后,文档和代码需要同时更新,否则工具会在最需要它的时候突然失效。
这类自动化不应该替人做决定。它只把重复读取、整理和导出变得可重复,把最终检查留给真正需要对结果负责的人。这样一个小脚本才不会因为“省了几分钟”而制造更大的误会。
脚本也应该有一个“停止条件”:页面结构不符合预期、学期选择不明确或返回内容为空时直接停下来。自动化最怕把异常当成正常,把一张空表导出成一个看似成功的文件。
这类脚本最重要的输出,是一份可以再次核对的数据文件。表头变化、缺失学期或服务端返回登录页时,程序应该停止并给出原因;宁可让一次任务失败,也不要安静地产出一份看起来完整的空表。
如果以后继续维护,我会把页面解析和文件写入拆开,并为解析器准备几份脱敏 HTML 快照。这样网络不可用时仍能测试结构变化,真实请求也不必反复触碰业务系统。
解析器测试可以直接使用几份脱敏 HTML:正常成绩、缺考标记、缺少某列、表头顺序变化,以及登录页被误当成成绩页。每份样本都应该有预期结构和失败原因,测试通过以后才允许进入文件写入阶段。
隐私边界也属于功能的一部分。导出的文件不应包含会话信息,日志只记录课程数量和结果状态,临时文件在任务结束后清理。自动化省下的时间,不能用暴露更大权限来换。