Back to skills
SKILL.md
Cnki Edu Exam Score Analysis
ASecurity中小学考试成绩数据分析与学情诊断:输出 HTML 报告、PDF 与 Excel 结果册三件套。
- 417 stars
- 0 votes
- 0 copies
- 1 view
- Added November 8, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 10 files and shows the line behind each finding
npx -y skills add infometa/workbuddyskills --skill cnki-edu-exam-score-analysis --agent claude-codeAre you the author of Cnki Edu Exam Score Analysis?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/infometa-cnki-edu-exam-score-analysis)---
name: cnki-edu-exam-score-analysis
display_name: 学业质量分析
display_name_en: Score Analysis
description: 中小学考试成绩数据分析与学情诊断:输出 HTML 报告、PDF 与 Excel 结果册三件套。
description_zh: 中小学考试成绩数据分析与学情诊断,输出 HTML 报告、PDF 与 Excel 结果册三件套。
description_en: Analyzes K-12 exam scores and diagnoses learning status, delivering an HTML report, a PDF and an Excel workbook.
category: education
version: 1.0.1
author: 知网 edu
---
# 中小学考试成绩数据分析 Skill
把一次(或多次)考试成绩数据,转化为老师能直接用于**讲评、家长会和教学改进**的完整分析报告。
**标准交付 = 三件套**:HTML 报告(可打印、可另存 PDF)+ PDF + Excel 结果册。Excel 结果册为默认产出,无需用户额外要求。
**`.json` 底稿不交付**(用户要求 2026-10-12):`analysis.json`(统计底稿)与 `narrative.json`(教学解读)
只是**中间产物**,生成后归档到交付目录下的隐藏子目录 `.底稿/`,`present_files` 只传三件套。
理由:老师拿到 `.json` 打不开也看不懂用途,摆在交付目录里只会显得杂乱;报告与结果册已经承载了
全部结论,底稿只在「追问某个数字 / 改话术重出」时才用得上。
## 🔐 前置权限校验(最高优先级,必须最先执行)
> 权限校验的「三态诊断 / 通用版兜底 / 强制转化卡 / 连接器加载指引」统一见本技能 `references/_shared.md`「一、权限固定提示」,本章节仅保留本技能专属说明,不重复展开。
> **权益 ≠ 引用(本技能适用)**:本技能**统计本体**(分数段、四率、得分率、临界生/分层名单、进退步追踪)全程基于用户上传的成绩数据,**纯模型生成、不依赖知网**。但「教学解读 / 改进建议」环节可引用知网实证文献(如《心理月刊》等考试焦虑、学习心理研究)作为专业增强——这属于**弱依赖 / 可选增强**,不是硬依赖:
> - 权益 `true`:解读可引知网实证文献提质;建议优先用 `mcp__<SERVER>__searchVectorBJ` 取真实文献,而非仅凭模型记忆,确保可溯源。
> - 权益非 `true`:统计照常出,解读改用通用教研经验,**不得标注"知网来源"、不得编造知网文献**(严守 `⛔ 严禁编造知网数据` 红线),可在对话交付说明里提示"接入知网后可获取实证文献支撑"。
> 权益是"能不能用知网能力"的闸门,不是"该不该引用"的开关;本技能的统计本体不引用,解读环节可引可不引。
## 何时使用
- 用户上传/粘贴成绩表(Excel、CSV、表格文本),要求分析成绩
- 用户要求"考试质量分析""学情分析""成绩分析报告""讲评优先级""临界生名单"
- 用户给出多次考试数据,要求个体进退步追踪
## 核心机制:学科分析模式(先判断,再执行)
| 模式 | 触发条件 | 执行方式 |
|------|---------|---------|
| A. 单科分析 | 只指定 1 个学科 | 全篇只分析该科,6 个维度全部围绕该科 |
| B. 多科分别分析 | 指定 ≥2 个学科 | 每科独立一章,6 个维度在每科内完整展开;最后加「跨学科横向对比」 |
| C. 全学科分析 | 说"所有学科/全部"或给出完整学科列表 | 同模式 B |
多科报告结构:核心结论摘要(跨学科视角,5 条)→ 各科完整 6 维度 → 跨学科横向对比 → 教学改进建议。
多科模式下,所有图表标题统一加学科名前缀(如「【数学】分数段分布」)。
## 工作流程
### Step 0 · 环境准备
脚本位于本 skill 的 `scripts/` 目录。**分析与渲染本身只用 Python 标准库**(图表为自研内联 SVG,不依赖
matplotlib 之类);唯一的外部依赖是 **openpyxl**,用在三处:① 读 `.xlsx` 成绩数据(`.csv` 不需要它);
② 生成 Excel 结果册;③ 跑 `scripts/selftest.py`(它要造测试用的 xlsx)。
**用哪个解释器(重要)**:**版本目录**下的解释器(`$HOME/.workbuddy/binaries/python/versions/<版本>/python.exe`)
**没有** openpyxl,直接跑会报 ModuleNotFoundError。请统一用受管 venv:
```bash
PY="$HOME/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
"$PY" scripts/exam_analysis.py ... # 建表 / 分析 / 渲染 / 自测都用它
```
> 路径一律写成 `$HOME/...`(Windows 下 `$HOME` 即用户主目录),文档里不写死具体用户名。
> 若环境变量未生效,可用 `echo "$HOME"` 核对后拼出实际路径。
缺依赖时用**同一个**解释器安装(不要用全局 pip):`"$PY" -m pip install openpyxl`。
`build_excel.py` 在缺 openpyxl 时会打印带解释器路径的安装指引并以退出码 2 结束,不会抛裸异常。
PDF 依赖本机 Edge/Chrome(脚本自动探测);`.xls` 旧格式需先转存为 `.xlsx` 或 `.csv`。
自测整条链路:`"$PY" scripts/selftest.py`(**48 个回归用例**,覆盖曾经踩过的坑);
`"$PY" scripts/make_sample_data.py --out 示例成绩.xlsx` 生成可复现的示例数据。
不确定用哪个工作表时先跑 `"$PY" scripts/exam_analysis.py --data 成绩.xlsx --list-sheets`。
### Step 1 · 执行前确认(必须,用户未说明时逐项询问)
1. 分析学科范围?(单科 / 多科 / 全部 —— 决定模式 A/B/C)
2. **每科满分是多少?**(最容易被忽略、后果最严重的一项 —— 见下方「满分设定」。
**分制多为 100 分(常规)、150 分、10 分、5 分**;语文/数学可能是 100 也可能是 150,
英语可能是 100/120,小学科常是 10 分制、5 分制。
**不要默认按学科名称猜满分**)
3. **主分析班级**是哪一班?(决定逐题统计的「班级层」——见下方「统计范围」。不指定则默认样本中的
第一个班;**多班样本务必问清**,否则班级层会分析成别的班,老师对着别人的班看半天)
4. 及格线、优秀线、低分线是否用默认值?(默认按满分 ×60%/85%/40%)
5. 是否有年级均分 / 区市均分作为对比基准?
6. 是否有历次成绩?**若有,历次表里有没有「序号」或「日期」列?**(没有的话必须让用户给出考试先后顺序,
否则趋势判定可能反过来 —— 见「历次成绩顺序」)决定维度 6 用折线追踪还是横截面分层
7. 是否有逐题得分与知识点归属?(决定维度 3、4 是否生成;没有就不生成这几节 ——
**绝不编造知识点**)。**逐题表里有没有「学号」列很关键**:有它才能把逐题统计分成「班级层 + 年级层」、
也才能**逐班**给出每道小题的得分率;没有的话两层数字相同、各班对比也不生成。
(小题分分析**只到班级与年级层,不下到每个学生**——用户要求 2026-10-11)
可提议由 AI 从题目内容推断知识点,但推断出的归属必须在逐题表的
「知识点 / 模块」单元格里写明「AI 推断」,并在交付说明里交代
8. 交付格式:默认 **HTML + PDF + Excel 三件套**。仅当用户明确说"只要 HTML/不要 Excel"时才调整——
记住"三件套"是默认约定,不要主动询问要不要 Excel。`.json` 底稿(`analysis.json` / `narrative.json`)
**不属于交付物**,归档到隐藏目录 `.底稿/` 即可,也不要问用户要不要。
用户已说"直接分析/不用问"时:满分仍**必须**确认(除非能从数据唯一反推,见下);其余按默认值执行并把
所做假设写进 `data_notes`(报告正文与 Excel 结果册都**不展示**,交付时必须在对话里复述)。
### 满分设定(最严重的一类错误:猜错满分 = 整份报告作废)
满分决定及格线 / 优秀线 / 低分线,进而决定及格率、优秀率、分数段、形态判定与分层名单。
**分制分布:常规分制为 100 分**,其次 150 分、10 分、5 分;120/200/750 等较少见。
「常规」只描述常见程度,**不是任何一科的默认值**——所以引擎的解析顺序是:
| 优先级 | 来源 | 行为 |
|--------|------|------|
| ① | `params.json` 的 `subjects.<学科>.full` | 直接采用,不提示 |
| ② | 命令行 `--full "语文=100,数学=100,物理=10"` | 直接采用,不提示 |
| ③ | 由该列成绩反推(唯一候选) | 采用,但**标记「待确认」**:写进 `meta.full_to_confirm`、各学科章首小字标「待确认」,Excel「01 阅读说明」置顶点名 |
| ④ | 推断不出 / 推断出多个可能 | **停止分析(退出码 3)**,打印待确认清单与补救命令,由你回头问用户 |
- 反推规则:取「最小的大于等于最高分的常见满分」,且要求最高分 ≥ 该满分的 85%
(例:最高 88 → 100 分制;最高 145 → 150 分制;最高 9 → 10 分制;最高 5 → 5 分制)
- **最高分 < 满分的 85%** 或**多个分制都说得通**(如最高 68 → 70/75/80 都可能)时,一定停下来问用户,
不要硬猜。用户一句话回答后用 `--full` 重跑即可(全流程自动,成本很低)
- 退出码 3 的清单里,候选分制已按常见度排好(**100 排首位并标「常规」**),并附「常见满分:100(常规)/
150 / 10 / 5」,把这段原样转达给用户最省事
- 退出码 3 表示「需要用户补充信息」,不是脚本故障
- 用户明确表态"不用问,就按常规分制"时,加 `--full-policy default`(**一律按常规 100 分制**兜底,
仍会写入「待确认」提示);若某科实际是 150/120/10/5 分制,必须用 `--full` 改正后重跑
- **交付前一定核对** `analysis.json` 的 `meta.full_to_confirm` 是否为空;非空时必须在交付说明里
向用户复述哪些学科的满分是推断来的
### 统计范围(务必向用户说清)
| 维度 | 统计范围 |
|------|------|
| 1 基础统计量 / 2 分数段 / 5 对比分析 | **主分析班级**(`--focus-class`);未指定则为样本中的第一个班 |
| 3 逐题得分率 | **两层 + 逐班**:班级层 = 主分析班级;年级层 = **全部样本(含各班)**;**各班层** = 每个班在每道小题上的得分率(用户要求 2026-10-10 / 11) |
| 年级层总览 | **全年级**(全部样本):班级总分排名、各学科班级排名、全年级各科四率与分数段 |
| 4 知识点 / 6 个体名单 | 与 1/2/5 一致,收敛到主分析班级 |
引擎会把实际范围写进 `analysis.json`(`meta.individual_scope` / `grade_scope_count` / `two_level_questions`),
并落在报告封面、逐题得分率小节的小字与分节标题、Excel「06 学生成绩与排名」标题上。
**单班样本会自动按班级名标注**(主表没有「班级」列也一样)——否则会出现封面写「初一3班」、排名表却写
「样本(含各班)」的矛盾标签。**不要**把全年级排名当成"班内排名"讲给老师。
**逐题表的「学号」列决定能分几层**(2026-10-10):
- 有学号 → 班级层 + 年级层两层并列,并**逐班**给出每道小题的得分率(报告维度 3 的「各班·逐题得分率」矩阵)
- 没有学号 → 两层数字相同(都是全部样本),各班对比也不生成——逐题表补一列「学号」即可全部启用
`--focus-class` 指定的班级在主表里**不存在**时,范围回退为全部样本,**封面标签也同步改成「全部样本」**
(`meta.focus_class_requested` 保留用户原本给的名字),避免封面写一个并不存在的班。
只分析**部分学科**时(主表里还有别的学科列没算进来),结果册里的合计列写「**所选学科总分**」而不是
「全科总分」——后者会让老师误以为那是学校层面的整份总分(`meta.partial_subjects` / `meta.total_label`)。
### 历次成绩顺序(容易出错,注意核对)
引擎判定先后的优先级:`--history-order` 显式指定 > 历次表的「序号」列 > 「日期」列 > 考试名称里的序号
(「第2次」<「第10次」,中文数字「第一次」与「二模」同样解析)。
- 「第1次月考 / 期中考试 / 第2次月考 / 期末考试」这种混排名称**建议**给「序号」或「日期」列,
否则用 `--history-order "第1次月考,期中考试,第2次月考,期末考试"` 显式指定
- **排不出顺序时引擎只警告、不阻断**(用户 2026-10-08 定):打印 `[警告]` + 补救命令,把告警写进
`data_notes`,报告「核心结论摘要」与维度 6 用醒目样式标注、Excel「07」也标注,
然后**照常出报告**——维度 6 的顺序存疑不该让其余 5 个维度也拿不到
- 为什么还要警告:按名称硬排会把「持续进步」判成「波动」、进步榜点错人,而且**不会报错**,
属于最危险的一类静默错误。看到这条警告就要在交付说明里提醒老师「趋势结论待核对」
- 有「序号」/「日期」列,或名称里都带序号(如「第1次月考…第10次月考」「第一次…第三次」)时
顺序可靠(`meta.history_order_source` = `explicit`/`seq`/`single`,`history_order_reliable=True`),
不会出现告警
- 历次表**只有 1 次考试**时,谈不上趋势:维度 6 自动退回横截面分层,并在 `data_notes` 里交代
- 交付前扫一眼 `analysis.json` 里某个学生的 `individuals.history[0].exams` 是否符合真实时间线
### Step 2 · 整理数据(xlsx/csv,三个工作表可选)
| 工作表 | 形式 | 必需列 |
|--------|------|--------|
| 主表(默认第一个) | 宽表,一行一个学生 | **学科成绩列**(列名=学科名);学号 / 姓名 / 班级**都可缺**,缺学号自动用行号代替 |
| `逐题`(可选) | 长表,**一行 = 一个学生一道小题** | 学科、题号、满分、得分(**学号** —— 有它才能分「班级层/年级层」两层、才能逐班给出每题得分率)、知识点(可选;**没有就不生成维度 4 / Excel 05,引擎绝不编造知识点**) |
| `历次`(可选) | 长表(或带学科列的宽表) | 学号、考试、总分;**强烈建议加「序号」或「日期」列**;**想对比历次各学科就再加学科列(语文/数学…)或改用「学号/考试/学科/分数」长表**;姓名 / 班级 / 排名 可选 |
- 学科列名支持别名:「道法」「德法」≡「道德与法治」,匹配用、输出不改名
- 表头前有合并大标题行会自动跳过;第一个工作表只是封面/说明页时会自动改用下一个有数据的表
- 完整字段说明、params.json / narrative.json 模板见 `references/data-and-params.md`
### Step 3 · 运行分析引擎
```bash
"$PY" scripts/exam_analysis.py \
--data 成绩.xlsx \
--exam-name "高二期中考试" \
--subjects "数学,语文,物理" \
--full "数学=150,语文=150,物理=100" \
--focus-class "高二(3)班" \
--history-order "第1次月考,期中考试,第2次月考,期末考试" \
--params params.json \
--out analysis.json
```
- `--subjects` 留空或填"所有学科"则自动识别数值列
- `--full` 各科满分(**推荐显式给**);`--full-policy default` 表示满分缺失时一律按常规 100 分制继续
- `--focus-class` 显式指定时,维度 3/4/6 也收敛到该班(范围统一)
- `--history-order` 可选:历次考试的先后顺序,逗号分隔;历次表既无「序号」也无「日期」、名称又排不出先后时**强烈建议给**(不给只警告不阻断)
- `--params` 可选:学科满分/自定义及格线/基准均分(模板见 references)
- `--list-sheets` 只列出工作簿里的工作表后退出,用于挑 `--sheet`
- 产出 `analysis.json`:全部统计结果,是报告与后续追问的数据底座
- **退出码 3 = 缺少必要信息**(目前只有「满分推不出」会返回 3),看 stderr 的 `[需确认]` 清单并回头问用户;
历次顺序判不出**不再阻断**,只打 `[警告]` 并在报告里标注(见「历次成绩顺序」)
### Step 4 · 撰写教学解读(narrative.json,可选但推荐)
`analysis.json` 只有数字;**教师视角的解读、归因和建议由你(AI)撰写**,写进 `narrative.json`:
```json
{
"summary": ["核心结论 1…", "核心结论 2…"],
"subject_notes": { "数学": { "stats": "…", "bands": "…", "questions": "…", "kp": "…", "comparison": "…", "individual": "…" } },
"cross_note": "跨学科对比解读…",
"improvement": { "common": ["…"], "kp_priority": {"数学": ["…"]}, "students": {"数学": ["…"]}, "actions": ["…"] }
}
```
不提供 narrative.json 也能出报告(脚本生成规则化兜底解读),但质量明显更低——**正式交付务必自己写**。
写作要求:结论必须有数字支撑;讲评建议落到具体题号/知识点;学生名单直接点名。
### Step 5 · 渲染三件套(HTML + PDF + Excel)
**一条命令出全套**(推荐):
```bash
"$PY" scripts/report_builder.py \
--analysis analysis.json \
--narrative narrative.json \
--out "高二期中考试_数语物_成绩分析报告.html" \
--pdf
```
- 输出单文件 HTML(图表内联 SVG,自包含,可浏览器打开、可打印、可另存 PDF)
- `--excel` **默认开启**:自动在同目录生成 `…_成绩分析结果册.xlsx`(**6–10 个工作表**:缺逐题数据时不生成
「04 逐题得分率」,缺知识点数据时不生成「05 知识点优先级」,单班样本不生成「09 年级班级排名」,
无历次成绩不生成「10 历次成绩对比」)。
用 `--no-excel` 关闭;用 `--excel-out 路径.xlsx` 指定输出位置。
- **缺失的板块直接不生成**:维度 3(逐题得分率)、维度 4(知识点热力图)在没数据时**整节不出现**
(标题、表格、图表都不渲染,章节名也会从「完整 6 维度分析」改为「N 个维度:…」),
报告里**不写任何「未生成」说明小字**——为什么没有只在**对话交付说明**里讲(用户要求 2026-10-11)。
**不要**再回头补「数据缺失」占位板块,也不要写占位文字。
- **没有知识点数据时**(用户要求 2026-10-11):凡是涉及知识点的地方**都不显示那一列 / 那一节**——
维度 4 整节不生成;**Excel 也不要有「05 知识点优先级」这张表**(含「01 阅读说明」的工作表导航,
不摆空表、不写「数据缺失」占位)。判定「没有知识点数据」只有一处规则(引擎 `norm_kp()`):
没有「知识点」列、整列为空、**或整列只填了 `-`「/」「—」「无」「未标注」「待定」这类占位符**,
都算没有——占位符最容易漏判,会造出名字叫「-」的假知识点、让 05 表凭空出现;
逐题表与高低分试题清单里不摆空白的「知识点」列;跨学科「各学科 TOP3 薄弱知识点」
**不整块消失**,退回按**每题得分率**给出「各学科 · 薄弱试题 TOP3」;教学建议的「知识点薄弱点
(讲评优先级)」**改按小题得分数据来分析**,标题换成「薄弱题讲评优先级(按小题得分率)」
- **标题序号全报告统一为「一、(一)1.、(1)a.、(a)」**(用户要求 2026-10-11):章节用 `一、`、
章内小节用 `(一)`、更细一级用 `1.`。序号由渲染脚本按**实际出现的标题**连续编号、**缺章节不跳号**;
**「目录」标题与「核心结论摘要」本身不编号**(目录里列出的章名照常带「一、二、…」,与正文同源)。
各学科章节内的维度小节**不再重复写「维度 N ·」**,只写小节名(如「(三)逐题得分率」「(四)对比分析」)
——两套编号并存会在维度缺失时错位成「(四)维度 5」
- **目录不要自动生成的阿拉伯序号**(用户要求 2026-10-11):目录用 `<ul>` + `list-style:none`,
**不出现 1./2./3.**(条目里已经有「一、二、…」,再加一层是重复编号)
- **含题号的表格一律按题号升序**(用户要求 2026-10-11):班级层逐题表、年级层逐题表、各班逐题矩阵、
知识点表的「涉及题目」、Excel「04 逐题得分率」——纯数字按数值排(1 → 2 → 10),非数字题号排在后面。
**讲评优先级 P1…Pn 另按得分率升序单独标注**,不再靠行序表达(行序现在是题号序,两者不是一回事)
- **清单项一律写纯文本**(用户要求 2026-10-11:「`<li>` 这个符号去掉,HTML 和 PDF 都改」):
列表外壳由 `ulist()` 统一加,且它会先 `esc()` —— 传进去的字符串**不要自己拼 `<li>` / `<b>`**、
**也不要自己 `esc()`**。自带标签会被转义成字面文本直接印在页面上(曾每份报告印 50 处 `<li>`);
自己 `esc()` 则会把知识点名里的 `&` 转两次。要加粗就写 `**…**`,交给 `inline_md()`。
- **姓名与学号各占一列**(用户要求 2026-10-11):报告的学生排名表、追踪表,结果册的 06/08 表都是
**学号一列 + 姓名一列**(不合并、不写成「张三(S01)」);数据里**没有真学号时「学号」列整列不出现**
——绝不用 `#1/#2` 这类兜底编号冒充学号(判定见 `meta.has_student_id`)
- **报告里不指向「随附的结果册」**(用户要求 2026-10-11):PDF 是单独一份,读者手上不一定有那份 xlsx,
写「完整数据见随附的结果册」会让人找不到。只交代「本表仅展示前 N 名,共 M 人」这种事实
- **高分/低分试题清单项不套 `<b>`**(用户要求 2026-10-11):直接写「第6题(共性错题):得分率 …」
- **维度 3 按学科统计,绝不混科**(用户要求 2026-10-10 / 11):1. 班级层逐题(本班,含讲评优先级)
2. 年级层逐题(全部样本,含判定)
3. **各班 · 逐题得分率**矩阵(行=题号、列=每个班 + 全年级)
4. **得分最低**的试题清单 5. **得分最高**的试题清单(按本学科分别给出)。
两层表格都按**题号升序**;高低分清单按得分率取前 5(语义如此,不按题号排)。小题分**不下到每个学生**
- **分数段一律显示具体分数**(用户要求 2026-10-11):维度 2 本班表及其「年级层 · 分数段分布」、
维度 5 的逐班分数段表,「分数段」列都按该科满分换算成**实际分数区间**(如「0 – 90 分」「135 – 150 分」),
不再单列「对应分区间」,也不用百分数
- **「各学科…」的清单/表格一律按学科分别成表**(用户要求 2026-10-11):**每张表正上方用小标题写出学科名称**
(如「【数学】分数段分布(全年级 · 满分 150 分 · 135 人)」「【语文】TOP3 共性错题」)。
适用范围:年级层「全年级各学科分数段分布」、历次「年级各学科四率」「班级各学科四率」、
跨学科「各学科 TOP3 薄弱知识点 / 各学科 · 薄弱试题 TOP3 / 各学科 TOP3 共性错题」
- **新增「年级层 · 班级排名与全年级指标」章节**(用户要求 2026-10-11,多班样本才生成):
班级总分排名 → 各学科班级排名(格内为**平均分** + 名次,名次按**得分率**排定)→ 全年级各学科四率
→ 全年级各学科分数段分布(**按学科分别成表**、表上方标学科名,分数段写成**实际分数区间**,不用百分数)
- **新增「历次成绩对比(年级 / 班级)」章节**(有历次表才生成):历次年级总分走势、历次年级各科四率
(**按学科分别成表**)、历次各班总分(单独一张表)与各科(**按学科分别成表**);
历次表只有总分时如实说明"只到总分维度",**不编造学科历次数据**
- **四率(优秀 / 良好 / 合格 / 不合格)为互斥四档**(用户要求 2026-10-11):优秀 ≥85%|良好 70–85%|
合格 60–70%|不合格 <60%,四者相加 100%,可与「分数段分布」对照;维度 1 里沿用的「及格率(≥60%)」
是累计值,与四率不在同一层,两个都保留、讲评时不要混用
- **报告与 Excel 结果册都不承载「数据说明」**(用户要求 2026-10-08):缺失值/统计范围/基准/来源/
未生成表的原因等数据质量交代一律不进正文,也不进结果册,改由 ① 各学科章首满分小字、
② 「核心结论摘要」的 ⚠️(顺序存疑时)、③ **对话交付说明**承载。封面与 Excel「01 阅读说明」
也不列「满分设定 / 分数线设定 / 数据来源」这类内部字段(满分与三条分数线已逐列写在
Excel「02 学科总览」,不需要再复述一遍)。
- `--pdf` 自动调用本机 Edge/Chrome 无头打印;失败则提示用户在浏览器"打印 → 另存为 PDF"(A4,边距 2cm)
- **页眉页脚必须关掉**(用户要求 2026-10-11):脚本已同时给 `--print-to-pdf-no-header` 与
`--no-pdf-header-footer`。否则每页页脚会印出 `file:///C:/…` 的本地路径与打印时间;
手工另存时也要在打印对话框取消"页眉和页脚"
- **PDF / Excel 文件属性里的生成侧元数据要清掉**(用户要求 2026-10-12):无头浏览器会把
浏览器 UA 与渲染引擎版本写进 PDF 的 `/Creator`、`/Producer`(`Mozilla/5.0 … HeadlessChrome/…`、
`Skia/PDF m…`),Excel 的工作簿属性会写库名 `openpyxl`——这些在「文档属性 / 文件 → 信息」里可见,
属于内部信息。脚本已自动处理(PDF 用**等长替换**抹掉、不动 xref;Excel 属性置空),
有残留会打 `[警告]`。交付前顺手扫一眼属性面板即可
- **PDF 与 HTML 同源**:报告正文改了就必须连 `--pdf` 一起重跑,不要只重出 HTML
- **报告与结果册必须同步重出**(用户要求 2026-10-11):报告里改了什么(题号升序、学号列、
分数段用具体分数…),Excel 结果册要跟着改并重出——两处讲的是同一件事,不能只改一头。
结果册「03 分数段分布」以**具体分数**为主列(「分数段(分数)」在「分段(占满分比例)」之前,
末档按 `min(hi, 1)` 收成满分、写成「135 – 150 分」,不要拼成「满分 分」);**Excel 单元格是纯文本**,表注里不要写 Markdown 的 `**`
- HTML/PDF/Excel 三者文件名同源:`{考试名}_{学科范围}_成绩分析报告.{html,pdf}` 与 `…_成绩分析结果册.xlsx`
(学科范围 ≤4 科连写如 `数语物化`,≥5 科写 `全7科`;**不含顿号**,避免路径问题)
**也可单独重跑任一件**:
```bash
# 只重出 Excel(改了数据或想要新命名时)
"$PY" scripts/build_excel.py --analysis analysis.json \
--out "高二期中考试_数语物_成绩分析结果册.xlsx"
```
Excel 生成器只依赖 `analysis.json`(学生成绩从各科 ranking 还原,无需原始成绩表,也不再需要 narrative.json)。
### Step 6 · 交付
用 **present_files 一次性呈现**,只传下面三项(第一项自动打开预览):
1. **HTML 报告**(会以内嵌浏览器打开)—— `高二期中考试_数语物_成绩分析报告.html`
2. **PDF** —— 同名 .pdf,用于打印/发家长/教研组
3. **Excel 结果册** —— `高二期中考试_数语物_成绩分析结果册.xlsx`(6–10 表,缺数据的表不生成)
**不要传 `analysis.json` / `narrative.json`**(见开头「`.json` 底稿不交付」)。
两者在渲染完成后移入 `<交付目录>/.底稿/`:
```bash
mkdir -p "<交付目录>/.底稿" && mv analysis.json narrative.json "<交付目录>/.底稿/"
```
底稿**不删**——它让「追问某个数字」不必重算、改 `narrative.json` 后可直接重出报告;
用户若明确要求清掉再删,并在回复里说一声。
补充:
- **交付物说明写在对话回复里,不要写进报告**:报告的正文到「教学改进建议」为止,不放
「附录 · 交付物与脚本说明」之类的章节(Excel 有几个表、文件名怎么命名、脚本怎么复用、配色代码
都是内部信息,老师/家长看的正式报告里出现这些是越界)。报告末尾只有一行页脚。
- 回复里也**不要罗列 `.json` 底稿**,只讲 HTML / PDF / Excel 三个交付物;底稿位置一句话带过即可
- 若用户要 Word:**本 skill 没有现成的 Word 脚本**,需按 `references/report-spec.md` 临时用 python-docx
从 analysis.json 重建;图表建议改为"先出 PDF 再转 Word"或截图嵌入,不要在正文里现画 PNG
- 交付时顺带说明本次的统计范围(逐题是**班级层 + 年级层两层**,班级层是哪一班)、被剔除人数、
以及**满分是否为用户确认**(`meta.full_to_confirm` 非空时必须点名复述),避免老师误读——
报告与结果册里都**没有**这些交代,全靠这句交付说明
- **逐题的两层与各班矩阵要一句话交代**:班级层是哪个班、年级层多少人、各班矩阵覆盖了哪几个班
(`meta.two_level_questions` / `meta.has_class_question_detail`);若逐题表没有「学号」列,
要明确说"本次各班逐题对比未生成,补一列学号即可"
- 本次未生成的板块(缺逐题/知识点数据时)也要一句话说明,并给出补数据的方式
(结果册的「01 阅读说明」只列实际生成的工作表,不再写"哪张表没生成、为什么")
- 脚本已固化在本 skill,下次换数据只需改 `--data / --subjects / --exam-name / --full`,三件套一起重生
—— 这句"下次怎么复用"属于回复内容,不要写进报告
### 原始导出表的整理提示(Step 2 补充)
学校/阅卷系统导出的 xlsx 常是"多工作表、每表带合并标题行"的格式(如:全科汇总 + 各科成绩 + 小题得分明细)。
引擎现在能自动**跳过表头前的合并大标题行**、并在**第一个工作表是封面/说明页时自动改用下一个有数据的表**;
但「一行一题的长表」仍不是合法主表,需先整理成标准输入:
主表(学号/姓名/班级/各科总分)+ 逐题长表(学号/学科/题号/满分/得分/知识点)。
可参考「按【学科】…明细表分块解析小题表 → 展平为长表」的做法:
按各科的明细表标题行分块,把「一行一题」的小题表展平成
`学号/学科/题号/满分/得分/知识点` 长表;原表没有知识点列时,**要么留空**(引擎会不生成维度 4、
不编造知识点),**要么**按题号/分值结构/教学进度推断模块归属,但推断出来的归属必须在逐题表的
「知识点 / 模块」单元格里写明「AI 推断」,并在交付说明里交代。整理时注意:各科满分用 `--full "语文=100,数学=100"` 显式给(勿依赖默认值);
「历次」表缺失时维度 6 自动转横截面分层;历次表里没有「序号」/「日期」时,要让用户给出考试先后顺序,
或直接用 `--history-order` 指定。
不确定用哪个工作表时先跑 `--list-sheets`。
## 数据异常处理(不要静默忽略)
引擎自动把缺失值、缺考、超满分/负分、未指定满分、基准缺失等写入 `analysis.json` 的 `data_notes`。
**报告正文与 Excel 结果册都不展示 `data_notes`**(用户要求 2026-10-08):这些交代只留在
`analysis.json` 与命令行输出里,**交付前必须逐条过一遍并在对话里复述**。检查该清单:
- 缺考/空值默认**剔除**(不按 0 分计);如用户要求按 0 分,需说明统计差异
- **被剔除的学生会逐个点名**落在 `analysis.json` 的 `data_excluded`,并写入 Excel「01 阅读说明」的
「未纳入统计的学生」表(这是结果册里唯一保留的数据质量交代——班主任对名单要用)。
老师对名单时能看出少了谁、为什么少——**交付时必须说一句"有 N 人被剔除"**,
别让对方自己发现(报告里已不展示这张表)
- **满分未确认**的学科落在 `meta.full_to_confirm`,各学科章首小字会标「待确认」、Excel「01 阅读说明」
也会置顶点名;交付时必须复述给用户(见「满分设定」)
- **重复学号**(同一学号出现多行)按同一人合并、**保留最后一条**,合并明细落在 `meta.duplicate_sids`
与 `data_notes`——过去会被当成两个学生,人数虚高、排名表里同一人出现两次
- **某科整列缺考/非数值**(整列一个分数都没有)时,该科退出分析并在 `data_notes` 里**点名**;
显式 `--subjects` 要求该科则直接报错。过去是静默丢科,老师会以为"本来就只考了这几科"
- **基准缺失**时用本次全体均分作年级参照,并明确标注"仅供参考"
## 常见问题
- **用户只粘贴了一段表格文本**:先整理成 xlsx/csv 再走 Step 3;列名以用户原表为准
- **表里没有学号 / 姓名 / 班级列**:都能缺,会自动降级(缺学号用行号、缺班级按同一群体处理)
- **学校导出的表打不开**:表头前的合并大标题行会自动跳过;第一个工作表是封面/说明页会自动换表;
但「一行一题的长表」不是合法主表,需先透视成宽表。报错信息会列出实际表头与可用工作表
- **脚本退出码 3、提示 `[需确认] ... 满分`**:这是设计行为,不是故障 —— 说明该科满分既没给、
也没法从数据唯一反推(例如最高分 68,70/75/80 分制都说得通)。把清单转达用户,拿到答案后用
`--full "学科=满分"` 重跑即可
- **报告里少了「逐题得分率」「知识点热力图」**:因为没有逐题/知识点数据,这两节**整节不生成**
(章节名会变成「N 个维度:…」)。不要虚构数据,也不要去补空板块;把
「学号/学科/题号/满分/得分/知识点」长表补上即可自动生成
- **逐题表没有「知识点」列(或整列为空、或只填了 `-` 「/」「无」「未标注」这类占位符)**:
维度 4 与 Excel「05 知识点优先级」不生成(占位符不算知识点数据——列在、每行都有字也可能一个真知识点都没有),
逐题表里也不留空白「知识点」列 —— **引擎绝不编造「未标注」这类假知识点**(那会让摘要写出
「共性薄弱知识点集中:数学→未标注」,是假教学结论)。补一列「知识点」即可自动生成
- **报告里没有「各班 · 逐题得分率」矩阵**:说明逐题表缺「学号」列(无法按班归属),或样本只有一个班。
此时班级层 / 年级层的逐题统计仍然正常;补一列学号(两端格式一致,注意前导零)即可自动生成,
Excel「04」也会多出各班的得分率列
- **报告里没有「年级层 · 班级排名与全年级指标」**:单班样本没有"班级排名"可言,该章整节不生成
- **报告里没有「历次成绩对比」**:没有历次表(或历次表只有 1 次考试)时不生成;
历次表只有「总分」列时该节只对比总分,补上学科列即可给出历次各科四率
- **`[警告] ... 无法判断先后顺序`(退出码仍是 0)**:历次表的「考试」列排不出真实时间序
(如混排的「第1次月考 / 期中考试 / 第2次月考 / 期末考试」)。引擎**照常出报告**,但维度 6 的
趋势判定 / 进步榜 / 需关注名单可能整体反向,并在摘要、维度 6、Excel 07 都做了标注。
交付时必须把这条提示转达用户;加一列「序号」/「日期」,或用 `--history-order "考试1,考试2,…"`
指定后重跑即可修正
- **改坏了 narrative.json**:不会影响交付 —— 脚本打印警告后按「无教师话术」继续出报告
(可选文件不该拖垮主交付;Excel 结果册已与 narrative 解耦,本来就不读它)。修正该文件后重跑即可恢复话术
- **没有历次成绩**:维度 6 自动改为横截面分层(尖子生/临界优秀/临界及格/学困生);
历次表只有 1 次考试时同样退回横截面分层
- **多班级数据**:按「班级」列自动分组,`--focus-class` 指定主分析班级,其余班级自动成为对比对象
- **用户追问某个数字**:直接读底稿回答,不要重算。底稿在 `<交付目录>/.底稿/analysis.json`
(`.json` 不交付,所以问「报告在哪」时不要提它,问「某个数字怎么来的」时再指路)
- **PDF 没生成**:脚本会打印警告;让用户用浏览器打开 HTML → Ctrl+P → 另存为 PDF(A4、边距 2cm、勾选"背景图形"),
或重跑时加 `--pdf-out 指定路径`
- **Excel 没生成**:多为当前解释器缺 openpyxl。按脚本打印的指引用**同一个**解释器
`"$PY" -m pip install openpyxl` 后单独重跑 `build_excel.py`
- **只想要 Excel**:`"$PY" scripts/build_excel.py --analysis analysis.json`(默认不生成 HTML/PDF)
- **只想要 HTML/PDF**:渲染时加 `--no-excel`
- **Excel 里要加图表**:结果册刻意只放**纯数据表**(分列、可排序、可透视),图表统一由 HTML 报告承载;
若要 Excel 原生图表,在 `build_excel.py` 对应 Sheet 里追加 `openpyxl.chart` 对象
## 详细规范(按需加载)
- `references/analysis-spec.md` —— 6 大维度完整计算方式、判定规则、图表要求
- `references/report-spec.md` —— 三件套文件结构、命名、配色、HTML/PDF/Excel/Word 格式要求
- `references/data-and-params.md` —— 输入数据 schema、params.json / narrative.json 完整模板、满分输入方式
- `scripts/exam_analysis.py` —— 计算引擎(成绩表 → analysis.json)
- `scripts/report_builder.py` —— 渲染引擎(analysis.json → HTML + PDF + Excel 三件套)
- `scripts/build_excel.py` —— Excel 结果册生成器(可被 report_builder 调用,也可单独运行)
- `scripts/make_sample_data.py` —— 生成示例数据,用于自测/演示
- `scripts/selftest.py` —— 回归自测(**48 个用例**),**改动任何脚本后都要跑**。
其中 5 条专盯「交付物不暴露内部元数据」:PDF 属性清理(等长替换 + xref 不失配)、
真实 PDF 无生成侧标识、HTML/Excel 无接口字段名与工具标识、技能文件无写死个人路径、页脚无工具标识
## 跨场景公共约定
权限固定提示 / 干净输出红线 / 触发词格式 / 版本与完工标准 / MCP 前缀自检:统一见 [_shared.md](references/_shared.md)。本 skill 的前置权限校验口径与「严禁编造知网数据」红线均与之对齐。
Files in this skill
- SKILL.md
- references/_shared.md
- references/analysis-spec.md
- references/data-and-params.md
- references/report-spec.md
- scripts/build_excel.py
- scripts/exam_analysis.py
- scripts/make_sample_data.py
- scripts/report_builder.py
- scripts/svg_charts.py
Attribution
Related skills
View all in data →Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.