表格急救箱 · 乱码与长数字抢救
一个能真正跑起来的表格故障急救工具。不是提示词模板——scripts/triage.py 是完整的诊断与修复引擎,纯 Python 标准库实现,零第三方依赖。
这个技能解决什么问题
国内办公场景里,表格事故高度集中在三类,且每一类都有明确的机械成因,因此可以被程序确定性修复:
| 症状 | 真实成因 | 能否修复 |
|---|---|---|
| 打开文件是一片「鏂囨。」「Îĵµ」 | 文件是 GB18030/GBK,却被按 UTF-8 打开 | ✅ 可完全修复 |
手机号变成 1.38E+10,末位全变 0 |
Excel 把长数字当数值处理,超过 15 位即丢精度 | ⚠️ 若源文件已损坏则不可逆,但可防止再次发生 |
工号 0012 变成 12 |
Excel 把前导零当数值前导零吞掉 | ✅ 可完全修复(转为文本列) |
| 某几行突然「串列」,整行数据错位 | 文本里含未转义的逗号,或导出被截断 | ✅ 可按表头重新对齐 |
| 表格中间夹着空行、重复表头 | 多段表拼接、导出模板残留 | ✅ 可清理 |
何时使用
当用户出现以下意图时使用本技能:
- 「这个 CSV 打开是乱码 / 显示问号 / 中文全变方块」
- 「Excel 打开以后手机号/身份证/订单号变成乱的了」
- 「这个表列错位了 / 数据串行了 / 有一行多出来一列」
- 「帮我清理一下这个表格」「把这张表修一下再发给我」
- 「导出的文件用 Excel 打开有问题」
快速开始
# 0) 可选:生成一份故障样本,先看看工具怎么工作
python3 scripts/make_sample.py
# 1) 体检:只读,不改动任何文件
python3 scripts/triage.py diagnose <文件路径>
# 2) 修复:输出新文件 + 体检报告,绝不覆盖源文件
python3 scripts/triage.py fix <文件路径> --to both
# 3) 已乱码的文本片段,直接还原
python3 scripts/triage.py unscramble "鏂囨。澶勭悊"
# 4) 环境自检(确认引擎在你这边可用)
python3 scripts/triage.py selftest
--json 输出结构化结果,便于程序化处理或与其它技能串联。
推荐工作流
- 先诊断,再修复。 永远先跑
diagnose,把结论读给用户听——尤其是「科学计数法已是源头损坏」这类不可逆情况,必须先讲清楚,避免用户误以为能一键恢复。 - 确认后再修。 修复属于写操作,产出新文件;如需覆盖既有产物必须显式加
--force。 - 交付三件套。
_fixed.csv(Excel 双击即正常)、_fixed.xlsx(长数字列已转为文本)、_report.md(体检报告)。报告可以直接转给同事解释问题原因。 - 把根因一并告知。 例如告诉用户「这个文件是 GB18030 编码,发给用 Mac 的同事会乱码,以后导出时选 UTF-8」。修数据不如修流程。
子命令参考
diagnose — 体检(只读)
python3 scripts/triage.py diagnose 订单表.csv
python3 scripts/triage.py diagnose 订单表.csv --json
输出内容包括:
- 编码判定:BOM 探测 + 多编码严格解码对比,给出编码、置信度与判定理由
- 分隔符判定:在逗号 / Tab / 分号 / 竖线中选出字段数最一致的那个
- 结构问题:全空行、字段数与表头不一致(区分偏少/偏多)、重复表头、可能的截断
- 列级风险:长数字列(≥11 位纯数字)、前导零列、疑似日期列、已是科学计数法的列
- 乱码探测:对疑似乱码内容给出还原文案
退出码:0 正常;2 输入错误(文件不存在、超阈值、编码无法解码)。
fix — 修复
python3 scripts/triage.py fix 订单表.csv # 默认输出 CSV + XLSX + 报告
python3 scripts/triage.py fix 订单表.csv --to csv # 只要 CSV
python3 scripts/triage.py fix 订单表.csv --to xlsx # 只要 Excel
python3 scripts/triage.py fix 订单表.csv --out-dir ./out # 指定产物目录
python3 scripts/triage.py fix 订单表.csv --encoding gb18030 # 强制指定源编码
python3 scripts/triage.py fix 订单表.csv --delimiter ";" # 强制指定分隔符
python3 scripts/triage.py fix 订单表.csv --no-report # 不生成报告
修复动作与判据:
- 编码归一:统一输出 UTF-8 带 BOM 的 CSV——这是「Excel 双击直接不乱码」的唯一稳妥做法
- 清理:删除全空行与重复表头行
- 串列校正:字段偏少 → 补空字段;字段偏多 → 把溢出内容并入最后一列(最常见的成因是末列自由文本里有未转义分隔符)
- 长数字保护:被判定为长数字 / 前导零的列,在 xlsx 中强制写成文本型单元格,Excel 不会再转科学计数法、不会再吞前导零
- UTF-8 输出:所有产物固定 UTF-8,避免二次乱码
unscramble — 乱码还原
python3 scripts/triage.py unscramble "鏂囨。澶勭悊"
python3 scripts/triage.py unscramble --file 乱码片段.txt
同时尝试四类常见 mojibake 形态并给出评分,取最优解:
latin-1 → utf-8:UTF-8 字节被当 Latin-1 读(Îĵµ型)gb18030 → utf-8:UTF-8 字节被当 GBK 读(鏂囨。型)latin-1 → gb18030:GBK 字节被当 Latin-1 读utf-8 → gb18030:GBK 字节被当 UTF-8 读(通常已有损,仅作参考)
评分低于原文时不予采纳,因此正常文本不会被强行"还原"。
引擎的判定原理(为什么结果可信)
编码识别不是靠猜后缀,而是靠内容打分:
- BOM 优先:命中字节序标记直接采信
- UTF-8 强判据:GB18030 编码的中文几乎不可能恰好构成合法 UTF-8,所以只要 UTF-8 能严格解码成功且内容可读,就判定为 UTF-8
- 可读性打分:只有「中文办公数据里常见的字符」才算好字符;错误解码产生的韩文、西里尔、天城文等乱字会被如实扣分(这一条是识别准确率的关键)
- 常用字乘数:同样都是汉字时,用常用字占比区分「正确解码」与「字都对但全是怪字」
长数字判定同样基于列级统计:某列中 ≥50% 的非空值匹配 11 位以上纯数字,才判定为长数字列,避免把偶发的长编号误报成整列风险。
安全边界
本技能在设计上即遵循最小权限原则,可安全用于企业环境:
- 只读输入:
diagnose不做任何写入;fix只写新文件,从不覆盖源文件;覆盖既有产物需显式--force - 不联网:引擎无任何网络调用,不发遥测,不上传任何数据
- 不调用外部进程:不使用
subprocess/os.system/eval/exec/pickle - 不生成公式与宏:产出的 xlsx 不含公式、不含 VBA 宏、不含外链,避免 CSV 注入与宏病毒风险
- 资源保护:默认单文件 64MB / 20 万行上限,超限需显式
--force,防止误吞超大文件拖垮环境 - 不开 xlsx 解压炸弹:读取 xlsx 仅解析 XML 必要部分,不落盘解压
已知限制
- 已丢失的精度无法找回:如果源文件里的身份证号已经变成
1.38E+10,精度在导出环节就没了,任何工具都无法还原。此时应引导用户回源系统以文本格式重新导出。 - xlsx 读取的是第一个工作表,多工作表文件请先拆分或手动指定。
- 合并单元格不会被自动展开,需要在源文件中先取消合并。
- 日期列的"序列号"问题:xlsx 中日期可能以数字序列存储,工具会将其列为「疑似日期列」提示,但不擅自转换格式。
- 不处理 .xls(BIFF 老格式):请先用 Excel 另存为 .xlsx 或 .csv。
- 不对数据业务含义作判断:工具只描述文件结构层面的事实,不臆测字段语义。
数据与合规声明
- 本技能仅在本机处理用户提供的文件,不收集、不上传、不留存任何数据。
- 示例数据(
examples/make_sample.py生成的样本)全部为虚构占位值,不对应任何真实个人或业务。 - 长数字列常涉及个人信息。工具输出报告时只摘取少量样例值用于说明问题,建议对含个人信息的文件在受控环境中处理。
- 全部代码与文档为本技能作者原创,以 MIT 许可证发布,不含任何第三方受版权保护的文本、代码或数据。