
大模型的训练语料已经悄悄进入“实体采购”阶段。最近行业里流传最广的一个做法是AI 公司批量收购旧书扫成电子文本之后再把纸质书销毁。第一反应是可惜第二反应是好奇为什么要买纸书再烧掉这件事拆开看本质是一个数据工程问题。当前互联网文本语料的质量正在下降重复内容、机器生成内容、低质量网文混杂在一起模型训练需要更干净、更结构化、更长上下文的文本。旧书恰好这个方向提供了一条稳定路径内容完整、逻辑连贯、知识密度高而且大量早期出版物已经进入公有版权领域授权链更清晰。买旧书、扫描、销毁并不是单纯为了“消灭实体书”而是为了在合规前提下拿到可用的训练语料同时避开仓储和复售带来的成本。这篇文章从训练语料采购、扫描 OCR 流程、数据清洗与去重、版权合规、存储成本、本地 AI 团队落地建议几个角度把这条链路说清楚。如果你正在做大模型数据建设或者想为自己部署的模型构建专属高质量文本数据集这篇文章值得收藏。1. AI 公司盯上旧书高质量文本语料为何稀缺先明确一个背景大模型训练离不开大量文本数据但“有数据”和“有干净的高质量数据”是两回事。早期做法是从互联网直接爬取后来慢慢发现这个方案有不少问题。1.1 互联网文本的痛点用爬虫拿网页数据速度快成本低但质量波动非常大。常见的几个问题重复内容多同一篇文章被多站点转载正文、标题、图片说明大量重复。夹杂噪声导航、广告、评论区、推荐列表混进正文。机器文本膨胀生成式 AI 普及后大量站点开始用模型自动生成内容真实信息密度下降。上下文不完整网页通常以短文为主很少有系统性的长文论述。直接把这些文本丢给模型训练会提高训练成本还会让模型学到大量重复和空泛表达。行业里经常讲“数据饥渴”更准确的描述是“干净长文本稀缺”。1.2 为什么旧书是高质量文本来源书籍和网页最大的区别在于结构。一本书有目录、章节、段落、注释内容经过编辑和校对错误率低叙事和论证是连贯的。这种文本正好适合训练模型把长文理解和总结。对于需要处理“长上下文”的场景书籍语料几乎是天然首选。旧书还有一个优势是版权状态更明确。出版时间较早、作者去世超过一定年限的书籍多数情况下已经进入公共领域企业可以对文本进行数字化和加工。对比那些来路不明的网络爬虫数据旧书语料的合规风险更低审计性更强。这也是“买旧书”这个动作出现的原因与其在版权状态复杂的电子书库里做吃力不讨好的筛查不如直接从旧书渠道采购把所有权和物理控制权抓到手里。1.3 “买书 扫描 销毁”模式的出现整个链路并不复杂批量采购旧书。对书进行整理、编号、扫描。用 OCR 和清洗流程把扫描件转成高质量文本。文本进入数据仓库作为模型训练语料。纸质书完成数字化任务后统一销毁。对很多团队来说“销毁”不是目标而是结果。纸质书保存需要仓库、温湿度控制、防虫防潮这是实打实的存储成本。同时实体书如果流入二手市场会出现“同一批内容既在训练集里又在公开渠道流通”的不可控情况。直接销毁管理成本最低。从数据工程角度看这种模式不是书被“浪费”而是把纸质书的物理形态转换成了数字形态并且通过销毁实体副本避免后续被二次传播。2. 从采购到销毁旧书语料生产的完整链路这一节把链路再拆细一点方便本地团队对照自己的流程。2.1 采购与物理整理采购环节需要考虑三件事来源、范围、状态。来源旧书店、古籍书店、批量回收渠道、图书馆淘汰批次。范围优先收公共领域书籍、无版权争议的出版物避免把仍在版权保护期内的新书大量混入。状态优先选页面完整、印刷清晰、没有水渍霉斑的书。扫描质量直接影响 OCR 成本。采购完成后每本书会分配一个唯一编号记录书名、出版年份、出版社、ISBN 或馆藏号等元数据。这一步为后面生成训练集元信息打好基础。2.2 扫描与图像预处理扫描不是简单“把书拍一遍”。大批量扫描通常要做裁边与方向校正。去黑边、去底色。矫正页面倾斜。检测空白页和重复页。生成统一分辨率的 TIFF 或 PDF 文件。图像质量直接决定 OCR 效果。扫描件分辨率过低小字号容易识别错误分辨率过高存储和计算成本又上去了。一般建议在 300-600 DPI 之间做测试以实际识别效果为准。2.3 OCR 识别与文本抽取OCR 是这条链路里最耗算力的环节。对于中文旧书常见选型是 Tesseract、OCRmyPDF 或商业 OCR 服务。通用流程是# 以 OCRmyPDF 为例先做图像优化再输出带文本层的 PDF # 实际运行时需要按本机环境安装对应语言包 ocrmypdf --clean --deskew --rotate-pages \ --language chi_simeng \ book_scan.pdf book_ocr.pdf # 再从 PDF 抽取文本 pdftotext -layout book_ocr.pdf book_ocr.txt可以用下面这段代码做首轮判断import re def clean_ocr_text(text: str) - str: # 统一换行符 text text.replace(\r\n, \n).replace(\r, \n) # 去掉明显的页眉页脚噪声具体规则按样本调整 text re.sub(r第\s*[0-9一二三四五六七八九十]\s*页, , text) # 去掉孤立的页码数字 text re.sub(r^\s*\d\s*$, , text, flagsre.MULTILINE) # 合并被换行拆散的段落 text re.sub(r([^\n])\n([^\n]), r\1\2, text) return text.strip() sample_text open(book_ocr.txt, encodingutf-8).read() print(clean_ocr_text(sample_text)[:500])这里没有固定规则能适配所有书。每类书的版式都不一样正确做法是先抽样 10-20 页人工标注一批常见噪声再写清洗规则。2.4 文本入库与实体处置文本抽取完成后会和元数据一起写入数据仓库。完成归档后纸质书进入销毁环节。销毁方式包括粉碎、化浆、焚烧按当地环保要求执行即可。从成本逻辑看买旧书、扫描、做文本清洗前期的固定成本并不低。但如果这批语料能持续用于多轮模型训练、微调、评测边际成本是摊薄的。销毁节省的是长期仓储和二次传播管理的隐性成本。3. 从扫描件到训练语料OCR、清洗与结构化“扫完就有数据”是错误的。扫描件到可训练文本之间还有一整条清洗流水线。3.1 版式分析与结构化旧书版式很复杂竖排、繁体、脚注、页眉、目录、索引。直接 OCR 后的纯文本通常是乱的。比较规范的做法是分段处理页面级分析识别正文区、页眉页脚区、注释区。段落级重组把跨页段落拼接起来。章节级拆分按目录结构把整本书拆成多个逻辑单元。元数据绑定一本书、一个章节、一个段落都保留来源编号。输出格式建议用 JSONL一行一个段落附带元信息{book_id: book_000123, chapter: 第一章 导论, text: 这里是清洗后的正文段落内容, source_page: 12, lang: zh}这种格式可以直接被后续的数据加载器读取。3.2 文本规范化与噪声清理文本规范化是整个数据管道里最枯燥但最重要的一步。常见动作包括全角半角统一。去除控制字符和不可见字符。繁体简体转换或保留按训练任务决定。修正 OCR 常见错误比如“0/O”“1/l”混用。去掉连续重复段落。下面给一个通用 Python 清理片段具体规则需要根据实际语料迭代import unicodedata import re def normalize_text(text: str) - str: # NFC 编码归一化避免同一个字出现不同码位 text unicodedata.normalize(NFC, text) # 常见标点替换 text text.replace(“, \).replace(”, \) text text.replace(’, ).replace(‘, ) # 去掉零宽字符 text re.sub(r[\u200b\u200c\u200d\u2060], , text) # 连续空格压缩 text re.sub(r {2,}, , text) return text.strip()这里没有银弹。清洗效果要以“人工抽样准确率”为判断标准而不是看脚本跑没跑完。3.3 去重训练语料的关键一步旧书语料的重复来源很多同一本书的不同版本、不同出版社的重印、再版时内容基本不变、多本书互相引用大段文献。训练时重复语料过多会让模型对重复模式过拟合降低泛化能力也会让评测指标虚高。常用的去重手段Exact Match 去重原文完全一致直接去掉。SimHash / MinHash 去重把文本转成哈希签名通过汉明距离判断相似度。LSH 索引在海量语料里快速找相似文本。段落级去重不是整本书去重而是按段落做去重避免大段引用造成冗余。示例import hashlib def text_hash(text: str) - str: return hashlib.sha1(text.strip().encode(utf-8)).hexdigest() seen set() dedup_lines [] for line in open(corpus.txt, encodingutf-8): h text_hash(line) if h in seen: continue seen.add(h) dedup_lines.append(line)这个示例只适合精确去重。要处理“同一段话换了几个人名”这类近似重复需要 MinHash 或更复杂的模糊匹配方案。4. 版权与合规边界买书销毁不代表可以随便用买旧书、销毁纸质书不意味着数字化后的文字可以随便用。版权问题不会因为“销毁了实体书”就消失。4.1 公共领域与版权保护期公共领域作品可以使用但判断标准要严谨。作者去世超过版权保护期通常可视为公共领域。有些旧书虽然年代久远但整理本、注释版、翻译版仍有独立版权。国内整理出版的“古籍今译”“校注本”同样受版权保护不能因为原著年代久就整体复制。所以批量采购后第一件事不是扫描而是做版权筛查。建议建立“版权状态表”逐本记录判定依据保留可审计记录。4.2 授权链条与使用范围对于仍在版权保护期内的书正确做法是获得授权作者授权、出版社授权或版权代理机构授权。授权书明确数字化、模型训练、商业使用等范围。绝不要因为“是公开销售的旧书”就默认可自由使用。购买实体书只获得了物理载体所有权数字化权和复制权是另一套规则。4.3 销毁环节的风险控制销毁纸质书可以降低物理传播风险但不能清除已经形成的数字化副本。所以数字化副本的权限管理要更严格训练语料库设置访问白名单。防止内部文本通过复制、下载、外链泄露。模型输出如果可能复现原文片段需要做输出过滤或内容溯源。涉及人脸图像、个人隐私信息的内容要遵循个人信息保护要求。合规不是一次性动作而是贯穿数据采集、处理、训练、部署全流程的审计体系。5. 资源占用与性能观察扫描语料项目的显存、存储与算力做旧书语料很少只有一个 OCR 脚本跑完就结束更多时候需要整套批处理流程。下面按资源维度做个梳理。5.1 存储占用扫描 PDF/TIFF一本 300 页的书300 DPI 灰度扫描原始图像通常在几百 MB 到 1GB 之间。OCR 后的文本层 PDF体积会小很多几十 MB 到一百 MB 左右。清洗后的 JSONL一本 30 万字的书纯文本大约 1-2MB。所以真正占空间的是扫描原图。推荐分层存储原图像文件放冷存储OCR 中间产物放热存储最终文本按版本放到训练数据目录。5.2 CPU 与 GPU 算力OCR 识别本身可以只依赖 CPU。跑 Tesseract、OCRmyPDF 这类工具CPU 数量越多并行处理的吞吐越高。如果采用深度学习 OCR 模型或者要在亿级文本上做模糊去重再考虑 GPU。显存占用取决于具体模型传统 OCR 工具基本不占用显存。深度学习 OCR / 文档理解模型按模型参数规模需要 6GB-24GB 不等实际占用需要以本机测试为准。大规模向量化去重要看嵌入模型和批量大小。对本地 AI 团队来说第一步应该先在小数据集上测出稳定的吞吐量再估算整体工期。不要一上来就堆资源。5.3 性能观察方法CPU 占用用htop或任务管理器观察 OCR 进程是否吃满多核。内存占用批量扫描时进程会一次性加载多个 PDF注意内存峰值。磁盘 IO图像解码和中间文件写入会产生大量 IOSSD 带来的提升非常明显。端口冲突如果后续接入 API 服务注意使用独立端口。# 查看 OCR 进程资源占用 htop -p $(pgrep -f ocrmypdf | head -n 1)如果批量任务卡住优先看日志里是单张图片报错还是进程整体阻塞。6. 接口 API 与批量任务把旧书语料管道工程化旧书信数字化不应该停留在“手动跑脚本”阶段。建议把它做成一个可重复的批处理任务系统。6.1 任务队列设计一个最小可用的任务队列包含四个环节扫描任务输入 PDF 或图片目录输出 OCR 文本。清洗任务输入 OCR 文本输出规范化文本。去重任务输入规范化文本输出去重后的语料。入库任务写 JSONL绑定元数据更新索引。用 Python 写一个最简调度器框架import os import subprocess from pathlib import Path INPUT_DIR Path(./scans) OUTPUT_DIR Path(./texts) OUTPUT_DIR.mkdir(exist_okTrue) def process_one_pdf(pdf_path: Path) - Path: output_pdf OUTPUT_DIR / (pdf_path.stem _ocr.pdf) cmd [ ocrmypdf, --language, chi_simeng, --deskew, --clean, str(pdf_path), str(output_pdf), ] subprocess.run(cmd, checkTrue) return output_pdf for pdf_path in sorted(INPUT_DIR.glob(*.pdf)): if pdf_path.name.startswith(_): continue try: result process_one_pdf(pdf_path) print(f[OK] {pdf_path.name} - {result.name}) except subprocess.CalledProcessError as e: print(f[FAIL] {pdf_path.name} - {e})批量任务最怕“一个文件卡死整个流程”。建议每个任务都加超时和失败重试。6.2 API 服务化已经把旧书语料处理流程做稳定的团队考虑走 API 集成到现有数据平台。常见的服务形态扫描上传接口。OCR 状态查询接口。清洗结果下载接口。去重任务提交接口。由于本项目没有公开标准 API下面给一个通用调用模板具体路径需要按你实际开发的服务调整import requests url http://127.0.0.1:8000/ocr_task payload { file_id: book_000123, language: chi_simeng, options: { deskew: True, clean: True, output_format: jsonl } } response requests.post(url, jsonpayload, timeout30) print(response.status_code) print(response.json())接口服务必须为每个任务返回唯一任务 ID并提供查询接口方便异步处理。6.3 失败重试与日志批处理任务不能只记录“成功/失败”要记录失败原因。建议日志字段输入文件名任务阶段失败原因重试次数当前时间默认策略单个文件失败 3 次后跳过并输出失败清单由人工检查。7. 常见问题与排查方法问题现象可能原因排查方式解决方案OCR 结果大量乱码扫描分辨率低、页面倾斜、语言包缺失抽查原图和文本层对比调整 DPI、启用 deskew、重新安装语言包繁体字/异体字识别率低模型语言包不匹配或未做图像预处理单独测试一页切换更合适的 OCR 引擎或添加字典清洗脚本处理后文本丢失段落规则写得太宽误删正文抽样对比清洗前后文本缩小正则规则范围先人工标注样本去重把不同书籍中有价值的内容误删去重阈值过高查看被删样本的相似度分布降低阈值或改按段落级去重批量任务卡住单文件异常导致进程阻塞查看日志和 CPU 占用增加超时机制和任务级隔离训练集里出现重复段落数据处理时漏掉去重步骤跑一遍哈希检查在入库阶段强制去重版权状态判定困难缺乏纸质出版信息核查版权页和版权登记信息建立人工审核流程无法确认则不入库磁盘空间快速耗尽原图 PDF 没及时归档检查存储占用原图转冷存储按批次删除中间产物8. 旧书语料生产的工程化建议这条链路能不能落地关键在工程化管理。给本地数据团队几点建议。8.1 先跑最小闭环不要一开始就采购几千本书。先做小规模样本10-20 本书跑完扫描、OCR、清洗、去重、入库。确认质量稳定后再扩大到批量采购。8.2 维护两份数据清单一份是“合法入库清单”记录每本书的采购来源、版权状态、处理版本。一份是“存疑清单”记录版权不确定、OCR 质量不合格、扫描状态异常的项。这两份清单要能对应到具体文本文件。做不到“一条数据能追溯到一本书”后面出问题就很难定位。8.3 分层存储建议目录结构data/ raw_scan/ # 原始扫描件 ocr_pdf/ # 带文本层的 OCR 结果 cleaned_text/ # 清洗后的文本 final_jsonl/ # 最终训练语料 logs/ # 批次日志原始扫描件不建议直接删除。清洗规则发生变动时需要能重新生成数据。8.4 合规先行所有环节里合规优先级最高。无法确认版权状态的书不要进训练集。涉及人脸、个人隐私的旧刊处理前要检查是不是符合个人信息保护要求。授权合作、商用发布之前务必完成版权复核。9. 总结与下一步“AI 公司买旧书再销毁”这件事核心不是“旧书值多少钱”而是“高质量文本语料怎么稳定获得”。互联网数据质量下降长文本稀缺旧书数字化正在成为一条不可忽视的训练语料补充路线。如果你在做大模型数据建设最先值得验证的是三条链路旧书版权状态筛查流程、扫描到 OCR 文本的完整管线、批量去重和来源追溯机制。最容易踩的坑是跳过版权审核直接扫描入库以及清洗规则定得太宽导致有效信息被误删。下一步可以继续扩展的方向包括把旧书文本和现有开源数据集迁移到统一的 JSONL 格式做跨数据源去重尝试使用更大的开源 OCR 模型提升古籍和繁体文本识别率以及在数据管道中接入模型输出过滤确保训练语料既能进得来也能管得住。建议把这个流程先做成小规模闭环再逐步扩大采购范围。