脚本 scripts/convert_marc.py 将 MARC 编目文件转为 UTF-8 BOM CSV,支持百万级记录。
当用户请求符合以下任一模式时,执行本技能:
head/cat 或 hexdump
-p N 预览模式,无需完整转换
先检查 pymarc 是否已安装。若未安装,执行:
pip install pymarc
完整转换(单文件):
python scripts/convert_marc.py <输入.iso> [输出.csv]
不指定输出路径时,在同目录生成同名 .csv。
预览模式(不写文件,仅打印前 N 条):
python scripts/convert_marc.py <输入.iso> -p 10
批量转换目录下所有 .iso 文件:
for f in /path/to/*.iso; do python scripts/convert_marc.py "$f"; done
脚本分两阶段执行,每阶段显示实时进度:
📖 data.iso (950.3 MB)
Phase 1/2: Scanning records + discovering columns...
→ 900,000 records, 156 columns (12.3s, 73,171 rec/s)
Phase 2/2: Writing CSV...
[█████████████▌ ] 45.2% 406,800/900,000 | 8,234 rec/s | ETA 1m0s
→ data.csv (452.1 MB)
⏱ Total: 127.5s | Overall: 7,058 rec/s
脚本执行后会打印:
检查预览行确认中文正常显示。若出现乱码,说明源文件编码非 GBK,需检查源文件实际编码。
NNN$x 标识符
references/cip_fields.md
| 数据规模 | 文件大小 | Phase 1 | Phase 2 | 总计 | 吞吐率 |
|---------|---------|---------|---------|------|--------|
| 200 条 | 0.2 MB | <0.1s | <0.1s | ~0.1s | ~3,000 r/s |
| 100,000 条 | ~100 MB | ~2s | ~15s | ~17s | ~6,000 r/s |
| 900,000 条 | ~950 MB | ~12s | ~110s | ~125s | ~7,000 r/s |
> 以上为参考估算(机械硬盘),SSD 更快。吞吐率随文件增大而提升(分摊 OS 开销)。
输入文件 数据.iso(200 条 CNMARC CIP 记录,GBK 编码):
$ python scripts/convert_marc.py 数据.iso
📖 数据.iso (0.2 MB)
Phase 1/2: Scanning records + discovering columns...
→ 200 records, 90 columns (0.0s, 9,031 rec/s)
Phase 2/2: Writing CSV...
[███████████████████████████████████] 100.0% 200/200 | 4,840 rec/s | ETA 0m0s
✅ 200 records (0.0s, 4,831 rec/s)
→ 数据.csv (0.2 MB)
⏱ Total: 0.1s | Overall: 3,114 rec/s
#1: 978-7-5306-9262-2 | 茶话会 | 周洁茹著 | 百花文艺出版社 | 2026 | CNY58.00 | I267
#2: 978-7-5306-9251-6 | 辰阳寓言故事集 | 傅胜必著 | 百花文艺出版社 | 2026 | CNY78.00 | I277.4
#3: 978-7-5306-9268-4 | 孤芳 | 王玉珏著 | 百花文艺出版社 | 2026 | CNY45.00 | I247.57
预览模式:
$ python scripts/convert_marc.py 数据.iso -p 5
📖 数据.iso (0.2 MB)
Phase 1/2: Scanning records + discovering columns...
→ 5 records, 54 columns (0.0s, 2,576 rec/s)
Preview (first 5):
#1: 978-7-5306-9262-2 | 茶话会 | 周洁茹著 | 百花文艺出版社 | 2026 | CNY58.00 | I267
#2: 978-7-5306-9251-6 | 辰阳寓言故事集 | 傅胜必著 | 百花文艺出版社 | 2026 | CNY78.00 | I277.4
...
中文乱码:脚本按 GBK → UTF-8 → GB18030 → Latin-1 顺序自动探测编码。若仍乱码,编辑脚本中 decode_bytes() 函数添加正确的编码到探测列表。
解析记录数为 0:文件可能不是标准 ISO 2709 格式。用以下命令检查文件头部:
head -c 24 文件.iso | xxd # 前 5 字节应为记录长度(如 3030373836 = ASCII "00786")
pymarc 报 TruncatedRecord:不要对记录字节做 rstrip(b'\x1d\x1e'),脚本已处理此问题。手动操作时务必以原始字节传入 Record()。
内存不足(超大文件):脚本自动检测文件大小,>1GB 启用 mmap 零拷贝模式(OS 按需分页,不会全量加载)。如仍不足,分拆源文件后分批转换。
转换中断:脚本无断点续传。中断后重新运行即可(输出文件会被覆盖)。对于超大文件建议先用 -p N 预览确认数据正确性。
stream_records() ← mmap (>1GB) 或 f.read() 全量 + leader切分
│
├─→ Phase 1: 仅采集列名 + 计数(极快,不解码内容)
│
└─→ Phase 2: convert_record() → csv.DictWriter.writerow()
逐条流式写入,O(1) 内存
核心原则:全程不累积 Record 对象。stream_records() 是 Generator,每条 Record 用完即释放。
编辑 scripts/convert_marc.py 中的 FIELD_MAP 字典增删映射项。未映射字段不会丢失数据——列名保留为原始 MARC 标识符(如 300$b)。
共 1 个版本