古诗词JSON数据集:结构设计、清洗实战与工程应用指南 📅 发布时间:2026/9/9 11:51:42 👁 浏览次数: 简介一份中国诗词大全 JSON 版完整压缩包源自 GitHub 的 chinese-poetry 开源项目专供需要本地化处理中文诗词数据的开发者、数据分析师与 NLP 研究者使用解决 GitHub 直接下载缓慢、clone 容易中断的痛点。压缩包共 1371 个文件以 1339 个 JSON 数据文件为主体覆盖唐诗、宋词、元曲、五代词及作者小传等结构化内容部分文件记录了数万首诗人作品与索引另含 Markdown 说明文档、SQLite 数据库、辅助 JavaScript 脚本及少量图片整包约 84.85MB便于离线检索与批量解析。目前已有 1065 人学习下载适合需要快速获取高质量诗词语料的中高级 Python 使用者。资源整理自社区开源项目目录层级清晰、文件命名规范可直接导入 Elasticsearch、MongoDB 等环境或用于构建诗词检索问答、文本挖掘与语料训练任务能显著节省网络访问与数据清洗时间。1. 为什么我要把《全唐诗》《全宋词》整理成一份JSON1.1 从一次古诗词App开发经历说起今年年初我给一个文化类App做内容模块需求很简单做一个每日诗词卡片每天推荐一首古诗词附带作者、朝代、正文。需求听起来不难但真正动手时才发现——拿不到一份干净、结构化、能直接入库的古诗词数据。网上搜一圈能找到的基本是这几种数据库备份文件.sql几十MB起步结构和字段千奇百怪Excel/CSV表格格式混乱有的把整首诗的标题、作者、正文挤在一个单元格里网页爬虫教程让你自己去抓公开诗词网站但那些页面本身就存在乱码、重复、缺字问题还有一部分是各种全唐诗大全的txt文本一行一首断句和标点全靠猜。折腾一周之后我放弃了决定按自己的标准整理一份诗词大全JSON版。这份数据的目标很明确拿到手就能用。无论是做App后端、写前端页面、搞NLP训练还是做个简单搜索工具都不需要再写一堆恶心的正则去清洗数据。文章末尾我会把这份JSON压缩包的关键结构和踩坑经验完整拆开讲希望能帮正在做类似内容的同学少走弯路。1.2 市面上的开源诗词库为什么都不顺手我不是说网上没有好东西像一些古籍数字化项目确实做得很好但它们的定位偏向学术研究不太适合直接对接业务开发字段太杂注释、异文、校勘记全堆在一起一个字段能写一整段话按古籍原书组织而不是按一首诗组织想要随机取一首诗还得自己切分编码和格式不统一同一部诗集里简体繁体混用、全角半角混用。我要做的是面向工程实践的版本以单首诗词为最小单元统一字段、统一编码、统一格式再压缩成zip发布。2. 数据结构设计一个字段一个坑我这样建模2.1 顶层结构分文件还是合成一个大JSON这是最早纠结的问题。全唐诗四万多首全宋词两万多首加上宋诗、元曲、诗经、楚辞、乐府等总量在十万首以上。方案有两种全部塞进一个超大JSON文件比如poetry_all.json按诗集或朝代拆分成多个JSON文件再用一个索引文件manage。我最终选了第二种。原因有三点单文件超过100MB很多编辑器和工具打开就直接卡死业务端往往只需要某一类数据比如只做唐诗功能没必要加载全部分文件之后Git diff、增量更新、按需下载都方便。压缩包里的顶层目录大致是这样poetry-json/ ├── README.md ├── index.json ├── 唐诗/ │ ├── 初唐.json │ ├── 盛唐.json │ ├── 中唐.json │ └── 晚唐.json ├── 宋词.json ├── 宋诗.json ├── 元曲.json ├── 诗经.json ├── 楚辞.json └── 乐府.jsonindex.json是一份总目录记录了每个文件对应的诗集名、朝代、收录数量、文件大小方便程序先加载索引再按需加载具体文件。2.2 单首诗词的字段设计与我的取舍每首诗词我定义为如下结构{ id: ts-0001, title: 静夜思, author: 李白, dynasty: 唐, type: 诗, collection: 唐诗·盛唐, paragraphs: [ 床前明月光, 疑是地上霜, 举头望明月, 低头思故乡 ], tags: [五言绝句, 思乡, 写景], notes: }字段设计上有几个有意的取舍值得说明一下正文为什么要存成数组而不是整段字符串因为绝大多数使用场景都需要按行处理——前端展示要逐行排版做飞花令要按句子匹配做鉴赏需要定位到具体某句。如果存成一个string每次用还得split而且不同来源的换行符还不一样\n、\r\n都有存成数组直接从源头规避了这个问题。为什么要加type字段诗/词/曲/赋因为唐诗宋词这种按朝代分类其实很粗糙——宋朝人也写诗唐朝也有词。type字段用来表达文体collection表达所属合集两个维度分开业务端筛选时很灵活。id命名的规律id前缀对应来源ts唐诗、sc宋词、ss宋诗、yq元曲、sj诗经、cf楚辞、yf乐府后面是四位序号。这样看到id就知道数据归属而且在合并数据时不会撞id。2.3 为什么我坚持保留俗体字和异体字清洗时最纠结的问题是要不要做繁体转简体我的决定是——保留原汁原味的字形录入但额外提供简体版本字段也就是说在paragraphs之外再加了一个可选的paragraphs_simple数组。如果原文是繁体paragraphs用繁体paragraphs_simple用简体。如果原文本来就是简体两个字段保持一致。原因很简单做文学研究的人需要看原文做产品的人需要给普通用户看简体两个需求都不能得罪。而且古诗词里很多字简体化之后反而丢失了平仄和韵脚的信息比如雲和云在某些语境下不能混用。这个设计牺牲了一些存储空间但换来了极大的兼容性。3. 数据清洗实录上万处标点和重复条目是这样修掉的3.1 初步去重同一首诗以不同标题反复出现整理过程中最大的噩梦是重复。同一首李白诗在《全唐诗》里收录的是正题但在《唐诗纪事》里可能换了标题或删了几句。如果只按标题作者去重基本没用。我的策略是按正文的指纹去重。具体做法import hashlib import json def poem_fingerprint(paragraphs): # 去掉所有非汉字字符拼接后做 hash text .join(paragraphs) text .join(ch for ch in text if \u4e00 ch \u9fff) return hashlib.md5(text.encode(utf-8)).hexdigest()两个关键点用MD5而不是直接比对全文是因为十万首诗做两两对比字符串比较太慢哈希可以提前索引只保留汉字去标点、去空格、去换行是为了避免同一首诗因为标点处理方式不同被误判成两首。指纹相同后再人工确认保留哪一条优先保留带注释的标题更规范的来自更权威合集的。3.2 标点与断句规范化全角、半角、弯引号原始文本来源复杂有从PDF转出来的、有从网页复制下来的、有扫描OCR的。标点问题千奇百怪英文标点混入比如用,代替弯引号“”和直引号混用句末有的用。有的用.有的干脆没有常见的是断句错误五言诗断成了床前/明月光、疑是/地上霜这样带斜杠的格式或者两句并成一句。我写了一个清洗管道按顺序处理把所有全角英文字母、数字转半角把半角标点统一转全角中文语境下句号、逗号、顿号、引号都该是全角的按韵脚句长规则做断句校验五言诗每句5个字、七言诗每句7个字如果句子长度不对就标记出来人工复核。断句校验这个步骤特别有用。因为古诗词有严格的字数规律一首七言绝句如果某句是8个字那基本可以确定清洗有问题。3.3 作者信息纠错与朝代补全作者字段的坑比想象中多同一作者多种署名李白有时写作李太白、青莲居士生卒年跨朝代的人归属争议大比如李煜算五代还是宋部分佚名作品的作者字段是空的。我的做法是维护一份作者规范映射表{ raw: 李太白, canonical: 李白, dynasty: 唐, alias: [青莲居士, 谪仙人] }先建立别名映射再在清洗时做全量替换。朝代字段不依赖原始文本而是以作者规范表为准这样一来李煜的作品默认为五代想看宋词的人即使不设置filter也基本不会混入。当然这个方案不是完美的——我承认它在文学考证上有妥协但对工程使用来说它换来了可预期的确定性。3.4 自动化校验让十万首诗词的清洗结果可验证清洗完不能直接打包发布必须有一套校验规则数量校验每个合集的实际条数和预期条数对比误差大于1%就报警字段完整性必填字段id、title、author、paragraphs为空的数据占比要低于0.1%长度校验五言诗的每句长度5七言诗每句长度7词牌不限制但上下句长度需要和词牌规则里的常见范围匹配JSON Schema校验每个文件都用预定义的Schema检查字段类型是否正确。这套校验脚本跑完之后我打包前还会做一次抽样人工阅读每个朝代随机抽20首逐首读一遍确认句子通顺、意境完整。机器校验防的是系统性错误人工抽读防的是机器判断不了的语义断裂。4. 压缩包目录详解拿到手先看这几份文件4.1 我的目录取舍为什么不放SQL和CSV确实有用户提过——能不能同时给一份SQL我的答案是JSON是源格式其他格式你需要时自己转。原因很直接JSON是树形结构可以直接表达一首诗下面的多个句子、多个标签而SQL要拆成多张表再join怎么存都别扭CSV对于含换行、逗号、引号的文本字段是灾难——诗词正文里既有逗号又有引号不做转义处理基本是坏的目前Python、JavaScript、Java等主流语言处理JSON都是原生支持解析开销可控。压缩包里除了前面提到的JSON文件还有一份README.md里面写了字段说明和取值枚举更新日志和版本号引用来源声明常见使用示例。4.2 三种常见语言的加载示例Python用于数据处理和脚本化使用import json with open(宋词.json, r, encodingutf-8) as f: data json.load(f) # 筛选李清照的词 for poem in data[poems]: if poem[author] 李清照: print(f{poem[title]}: {poem[paragraphs][0]})Node.js用于前端或服务端const fs require(fs); const data JSON.parse(fs.readFileSync(宋词.json, utf-8)); const liQingzhao data.poems.filter(p p.author 李清照); console.log(liQingzhao);Java用于Android或后端// 用 Jackson 解析 ObjectMapper mapper new ObjectMapper(); JsonNode root mapper.readTree(new File(唐诗.json)); for (JsonNode node : root.get(poems)) { if (李白.equals(node.get(author).asText())) { System.out.println(node.get(title).asText()); } }5. 使用JSON数据时最容易踩的坑以及我如何规避5.1 编码问题UTF-8带不带BOM差别很大这是最隐蔽的一个坑。在Windows上默认的记事本保存UTF-8文件时会自动加上BOM头EF BB BF这会导致JSON解析器直接报错或者解析出不可见字符。Python的json.load遇到带BOM的文件会直接抛json.decoder.JSONDecodeErrorJava的Jackson在部分版本下会遇到Invalid UTF-8的问题。打包前我用脚本扫描了所有文件把BOM全部去掉统一为UTF-8无BOM。具体命令# Linux / macOS find . -name *.json -exec sed -i 1s/^\xEF\xBB\xBF// {} \;5.2 Java后端场景大写字母开头的字段变小写之前有读者问过我解析后Title变成了title查了半天不知道哪里出了问题。这是Jackson等JSON库的命名策略导致如果Java Bean的字段是String Title默认的camelCase策略会把它序列化成title而如果JSON里本来就写了Title反序列化时又匹配不上。我在README里特别提醒了这一点如果你们的后端接口要用JsonProperty注解显式指定字段名不要依赖默认命名策略public class Poem { JsonProperty(id) public String id; JsonProperty(title) public String title; JsonProperty(author) public String author; JsonProperty(paragraphs) public ListString paragraphs; }这样写最保险不管把JSON文件喂给哪个JVM语言字段映射都不会跑偏。5.3 前端场景[object Object] is not valid JSON的真相很多网页在加载JSON时会在控制台报一个非常误导人的错Uncaught SyntaxError: [object Object] is not valid JSON这个错误99%的情况是你试图对一个JavaScript对象调用JSON.parse而不是对字符串调用。比如const data { title: 静夜思, author: 李白 }; // 错误写法JSON.parse 接收了一个对象 const result JSON.parse(data); // 正确写法 const result JSON.parse(JSON.stringify(data)); // 或者如果是从外部 fetch 得来response.json() 本身已经是解析后的对象 const result await response.json();如果发现报错中出现了[object Object]第一反应应该是去检查传给JSON.parse的参数是不是一个对象而不是一个字符串。5.4 浏览器直接打开JSON文件的白屏问题用file://协议直接在Chrome或Edge里打开本地JSON并尝试用fetch加载会被浏览器的同源策略拦下来窗口一片空白。这和你的代码无关是安全策略。实际上我在README里就对前端开发者做了如下建议在本地开发时起一个简单的静态服务而不是直接双击HTML文件。最简单的方式# 在项目根目录执行 python3 -m http.server 8080 # 然后浏览器访问 http://localhost:8080/index.html这样fetch(唐诗.json)才能正常工作。5.5 大JSON文件解析的性能问题说句实话即使是单朝的JSON也有几十MB。老式做法是一次性JSON.parse或json.load全量读入在小设备上确实可能卡顿或内存溢出。我做了两件事来缓解分文件存储按需加载在README里推荐流式解析方案。Python端可以用ijson做流式解析前端可以用fetch加流式读取ReadableStream或者做懒加载在滚动到对应位置时才加载具体文件。这个数据集毕竟不是为大数据场景设计的如果你要做的是千万条的全文分析建议先导入ClickHouse或MongoDB再建立索引。不要让JSON文件本身承担数据库的职责。6. 从JSON到应用几个落地场景与我的扩展建议6.1 全文搜索与条件筛选拿到JSON后最常见的需求就是按作者查诗按朝代筛选按标签找主题。最简单暴力的方式是加载后遍历过滤数据量在十万级别时性能其实还能接受但如果要做全文搜索搜诗句中的某个词建议导入Elasticsearch或SQLite的FTS5。举个例子用SQLite做诗句搜索CREATE VIRTUAL TABLE poems_fts USING fts5(title, author, paragraphs);把JSON数据灌进去之后搜明月只需要一条SQL速度快很多。6.2 随机诵读与每日推送paragraphs设计成数组的好处在这个场景体现得很充分。做每日诗词卡片时只需要加载对应朝代的JSON随机取一个index从paragraphs里按行渲染。不需要再做任何字符串处理直接交给前端展示。我自己的小工具还加了一个飞花令模式——给一个关键字遍历所有诗句匹配包含该字的句子paragraphs数组逐条匹配逻辑非常简洁。6.3 NLP分析与古诗生成如果要做古诗风格分析建议使用paragraphs_simple简体版本做向量化保留的繁体字段做对照。注意一点不要对平仄做自动推断除非你清楚古音和今音的差异否则拿普通话四声去套平仄结果会很离谱。6.4 我实际做完之后的几个体会整理这套诗词JSON的过程本质上是在做一次内容工程。它不像写业务代码那样有即时反馈而是一个需要耐心校验和反复修正的过程。但做完之后后续开发效率提升是肉眼可见的新功能不再被数据清洗卡住数据质量的可预期性非常高出问题能快速定位到具体某一首诗的某一句而不是在一堆txt里大海捞针和其他项目对接时直接甩一个README加JSON文件过去别人照着示例就能跑通。最后分享一个小技巧发布数据包时一定要在index.json里明确写一个version: 1.0.0字段。后来你会发现这是整个包里性价比最高的一个字段——别人引用数据的时候能说清楚用的哪个版本你更新数据的时候也不会引起下游一片乱。就这个字段能省掉你至少十次解释你用的为什么和我用的不一样的沟通成本。本文还有配套的精品资源点击获取