
简介中华古诗词数据库是面向文学研究者、数据爱好者和前端开发者的开源 JSON 数据集收录 5.5 万首唐诗、26 万首宋诗、2.1 万首宋词及元曲等古典文集包含唐宋近 1.4 万诗人和两宋 1.5 千古词人的作者信息。压缩包共 2000 个文件以 1978 个 JSON 数据文件为主辅以 16 个 Markdown 说明文档、Python 处理脚本、JS 示例和索引文本整体约 91.18MB按朝代、文体与作者分层组织便于快速定位。已有 822 人学习下载。使用者可直接获得结构化语料免去自行爬取与清洗的麻烦适用于诗词检索网站、文本分析、语料库建设及文化类应用原型也能作为中文分词、实体识别等实验的数据基础。1. chinese-poetry这个古诗词数据库到底解决了什么问题很多做 NLP、搞数据分析和做诗词教学工具的朋友第一次见到 chinese-poetry 这个项目时都会误以为它只是一堆 txt 文本的堆砌。但当你真正把数据拉下来解压后看到按朝代、作者分门别类的 JSON 目录时才会意识到这其实是一座已经清洗过的结构化诗词语料库。我最早接触它是为了做“以诗会友”的关键词检索原型结果发现它比我自己去爬古诗文网要省掉至少两周的清洗时间。这个项目本质上是把全唐诗、全宋词、元曲、论语、诗经等经典文本按统一 JSON 格式整理好附带作者小传、卷册信息并提供了配套的 Python 库和命令行工具方便你在本地跑检索、统计和模型训练。适合谁用适合有明确数据需求的开发者和研究者——比如你想训练一个写诗模型或者做作者风格向量化而不适合只是拿来做随手查询的普通读者。2. 先跑通本地最小环境从克隆到第一次检索数据2.1 拉取项目与核对目录结构的正确姿势chinese-poetry 项目的标准获取方式是直接 git clone 整个仓库到本地但我建议你一开始不要 clone 全部历史因为仓库体积会随着版本迭代变大而且 JSON 文件数量很多浅克隆能帮你更快进入实操状态。常见做法是git clone --depth 1 https://github.com/chinese-poetry/chinese-poetry.git cd chinese-poetry这里--depth 1表示只拉取最新一次提交不保留历史版本。对绝大多数场景来说最新的数据集精度已经够用而且浅克隆能明显减少网络传输和磁盘占用。完成之后你会看到 chinese-poetry/ 目录下有几个核心子目录其中全唐诗、全宋词、元曲、论语、诗经等都在不同子目录里。2.2 用 Python 快速核验数据完整度项目拿下来之后第一件事不是急着写业务代码而是先做一次基础的数据台账核验看看实际 JSON 文件数量和整体体积是否符合你的预期。直接跑下面的脚本即可import os from collections import Counter poetry_dir chinese-poetry ext_stats Counter() file_count 0 for root, dirs, files in os.walk(poetry_dir): for f in files: ext os.path.splitext(f)[-1].lower() ext_stats[ext] 1 file_count 1 print(总文件数:, file_count) print(扩展名分布:, dict(ext_stats))这段代码做的事很简单递归遍历目录统计每个扩展名的出现次数。我看到很多新手第一次跑 clone 后直接就去读全唐诗结果导错路径或者解压不完整代码一报 KeyError 就懵了。先用这个小脚本建立“数据台账”能让你在后续遇到文件缺失时迅速判断是网络传输问题还是本地磁盘问题。更关键的是chinese-poetry 的主数据是纯 JSON实际没有任何外层压缩包这一点和很多旧式语料库不同。2.3 第一次按作者检索的极简实现数据核验无误后我一般会先写一个非常简单的按作者检索函数用来感知数据结构和耗时水平。全唐诗的 JSON 通常按卷存储以poet.tang.$id.json或$id.json的形式命名每一卷里是一个数组其中每首诗包含author、paragraphs、title等字段。极简实现如下import json def search_by_author(author_name, base_pathchinese-poetry): results [] # 全唐诗目录视项目版本不同有所差异这里做两层目录扫描 for sub_dir in [chinese-poetry, 全唐诗]: full_dir os.path.join(base_path, sub_dir) if not os.path.isdir(full_dir): continue for fname in os.listdir(full_dir): if not fname.endswith(.json): continue with open(os.path.join(full_dir, fname), r, encodingutf-8) as fp: poems json.load(fp) for p in poems: if p.get(author) author_name: results.append(p) return results这段代码没有做任何索引优化只是全量扫描。如果你只查一个作者跑完整个全唐诗目录大概需要几十秒这取决于磁盘速度。逻辑上它就是遍历所有卷宗 JSON 文件把每个文件里的诗数组依次读入内存再根据author字段精确匹配。之所以不限定具体文件名是因为 chinese-poetry 的卷目录命名在历史和版本迭代中略有调整硬编码路径很容易踩坑。3. 把诗词数据变成可操作的数据集结构化抽取与入库3.1 为什么不能直接用原始 JSON 做数据分析和模型训练原始 chinese-poetry 的 JSON 对我们人来说已经很规整但直接把它喂给统计模型或数据库时会遇到几个麻烦。首先诗词正文的paragraphs是一个字符串数组每行一句可模型训练通常希望获得拼接后的长文本或按句切分的短文本。其次很多诗的“标题”带有“卷二十八”、“同前”等说明性文字导致同一首诗在不同卷中可能重复出现直接计数会把重复数据当成有效样本。第三部分诗篇存在“有序 正文”共存的情况即标题后有一段类似“并序”的文本这段文本与诗正文混在同一个paragraphs中不做清洗会把序言也当成诗的训练语料。我做过一次实体统计全唐诗去重前后的数据量差别不小这正是因为你若不过滤那些带“序”的诗篇模型会学到很多不符合格律的句式。所以结构化抽取的第一步就是过滤掉title中含“序”或“并序”的条目再把paragraphs用换行符合并成完整文本最后做成标准的 CSV 或 Parquet 文件。3.2 用 Python 把 JSON 转成干净的训练集这里我贴一段轻量但完整的数据清洗方案它解决的是从 chinese-poetry 原始 JSON 到一张可用表结构的转换import json import os import csv def clean_poem(poem): title poem.get(title, ).strip() author poem.get(author, ).strip() paragraphs poem.get(paragraphs, []) # 过滤带序的诗标题里出现“序”字多半不是正文 if 序 in title: return None if not paragraphs: return None full_text \n.join(paragraphs).strip() return { title: title, author: author, content: full_text, dynasty: 唐 # 根据目录预先指定 } def convert_to_csv(src_dir, out_csv): rows [] for fname in os.listdir(src_dir): if not fname.endswith(.json): continue with open(os.path.join(src_dir, fname), r, encodingutf-8) as fp: poems json.load(fp) for p in poems: cleaned clean_poem(p) if cleaned: rows.append(cleaned) with open(out_csv, w, encodingutf-8, newline) as fp: writer csv.DictWriter(fp, fieldnames[title, author, content, dynasty]) writer.writeheader() writer.writerows(rows)这里要注意newline这个参数在 Windows 下如果不加CSV 文件里会出现空行后续导入 MySQL 或 pandas 时会产生意外的 NaN 行。另一个关键点是把正文paragraphs的数组字符串用换行符拼接而不是用空格理由是保留原诗的换行结构也能让之后做句子切分时更方便。清洗策略里使用if 序 in title存在一定误杀因为个别正常标题也可能包含这个字但实际统计下来概率极低不会对模型训练产生显著偏差。3.3 把清洗结果导入 SQLite 做本地检索一旦把数据导出成 CSV你就可以马上用 SQLite 建表查询这样后面做关键词检索或分页浏览会比直接解析 JSON 高效很多。常见的导入命令是sqlite3 poetry.db EOF DROP TABLE IF EXISTS poems; CREATE TABLE poems ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, author TEXT, content TEXT, dynasty TEXT ); .mode csv .import clean_poems.csv poems CREATE INDEX idx_author ON poems(author); CREATE INDEX idx_title ON poems(title); EOF这段命令中.import会按 CSV 列顺序逐行导入前提是你的 CSV 列顺序与建表字段顺序一致。建两个单列索引idx_author和idx_title能让按作者和按标题的查询加速明显但当数据量大到百万级我还是建议换用 PostgreSQL 或者直接用 pandas 的内存查询。SQLite 适合单机快速验证不适合做高并发或复杂 JOIN 的服务端存储方案。很多入门用户在这里容易踩坑CSV 里的引号转义没处理好导致content字段里的换行符被 SQLite 视为新记录解决方法是导入前先确认所有字段都已用双引号包裹。4. 向数据库新增和同步数据的现实方案增删改查与版本更新4.1 官方数据集更新机制与本地 fork 管理chinese-poetry 官方仓库会不定期更新比如修正错字、增补作者小传和补充新的卷册。直接git pull就能把最新数据拉到本地但问题在于如果你在本地已经清洗并入了库每次拉取上游版本时相当于远程数据源发生了整体变动你的本地清洗脚本和数据库结构未必能平滑同步。我遇到的真实情况是项目方有一次调整了全唐诗的子目录结构把原来的chinese-poetry/全唐诗改成了带卷标的新目录名导致我原先写死的路径全部失效。稳妥的做法是复制一份数据目录作为“可操作副本”然后只在副本上做清洗和入库官方仓库保留原始状态用于定期拉取更新。这样即使上游目录结构变化你也只需要对比目录树不需要重新清洗整库。同步检查可以这样操作git fetch origin git diff HEAD origin/master --stat -- chinese-poetry/全唐诗 | tail -20这段命令会拉取远程更新但不自动合并然后统计全唐诗目录下的变更文件数量。如果发现大量文件变化我会优先查看变更文件的样例再决定是否重新清洗。永远不要在生产环境直接覆盖你的查询数据库我因为一次手滑把整库重建导致自己工具里的收藏数据全丢了从那以后都强制使用副本工作流。4.2 在 SQLite 上做增删改查的标准套路当你把 chinese-poetry 数据清洗入库后业务上最常用到的操作无非是查作者、查标题、查内容片段、删除无效记录、修正个别错字。SQLite 上的基本增删改查写法如下-- 按作者查询 SELECT title, content FROM poems WHERE author 李白 LIMIT 5; -- 按内容模糊查询 SELECT title, author, content FROM poems WHERE content LIKE %明月% LIMIT 10; -- 删除标题为空的脏数据 DELETE FROM poems WHERE title OR content IS NULL; -- 修正某个已知错别字谨慎操作 UPDATE poems SET content REPLACE(content, 仑, 伦) WHERE content LIKE %仑%;增删改查这件事本身并不难难在语义边界。比如LIKE %明月%在 SQLite 里默认按字节匹配是全表扫描数据量在十万条内没问题一旦上了百万级就会减速到秒级。更关键的是诗词内容里同一个汉字的不同字形比如“裡”与“里”会影响匹配结果我通常会在写入前做一次繁简和异体字统一否则后续查询会出现明明读着相似的句子却查不到的情况。另外REPLACE(content, 仑, 伦)这类全局替换必须相当克制因为同一字在不同诗句里的语义可能不同尤其在古籍数据中异体字替换需要保守处理。4.3 用 Python 与数据库交互时防止乱码和路径坑代码里直接拼 SQL 容易遇到中文编码问题尤其 Windows 控制台默认编码不是 UTF-8 时中文查询条件可能直接被截断或乱码。最稳妥的做法是用参数化查询比如import sqlite3 conn sqlite3.connect(poetry.db) conn.execute(SET NAMES utf8) # 仅用于部分数据库驱动SQLite 本身不需要 cur conn.cursor() author 苏轼 cur.execute(SELECT title, content FROM poems WHERE author ? LIMIT 10, (author,)) rows cur.fetchall() for r in rows: print(r[0], r[1][:30])?占位符会由驱动自动做编码处理避免因为手动拼接 SQL 而导致引号转义和编码问题。另一个很隐蔽的坑是 Windows 命令行直接print中文内容时输出到控制台容易报 UnicodeEncodeError这通常不是数据本身的问题而是控制台编码不是 UTF-8。一般做法是先把结果写入文件或用环境变量把控制台代码页改为 UTF-8 后再打印。很多人在这里翻车误以为数据库数据是乱码其实只是终端显示问题。5. 避坑清单chinese-poetry 实践中的 5 个真实踩坑记录5.1 现象读取 JSON 时报 UnicodeDecodeError原因部分 JSON 文件头部的编码声明与实际内容不一致或者在处理过程中使用了系统默认编码。解决所有文件操作统一显式指定encodingutf-8并且不要相信代码编辑器右下角的编码提示直接在读取函数里强制指定。5.2 现象数据统计数量与官方 README 不一致原因官方文档里的“五万首”等数字是某次版本快照后续更新增补了内容而你本地拉取的可能是历史版本。解决不要拿自己的统计数和网上旧帖子硬比以每次本地全量扫描结果为准并在文档中标注数据拉取日期。5.3 现象按作者检索时漏掉“李白”的部分诗原因部分诗篇的作者字段为空或因版本问题作者写在标题后缀里如“李白 二首”这种变体。解决数据清洗时增加一个逻辑——当author字段为空时尝试从标题尾部约两到四字中提取人名但这属于最后手段宁可少收也不误匹配。5.4 现象入库后前后鼻音、多音字查询不准确原因SQLite 默认的LIKE不支持中文拼音匹配而且多音字如“行”、“重”在诗词里输入哪个读音全看语感检索结果自然不准。解决在表结构中增加一个pinyin字段导入数据时用拼音库自动生成全拼查询时先用拼音做候选集再对候选集做精确文字过滤能大幅提升命中率。5.5 现象git pull 后本地修改冲突仓库无法更新原因你直接改了仓库里的 JSON 文件或者在工作目录下放了多余文件拉取上游时发生合并冲突。解决从第一天起就把 chinese-poetry 仓库当作只读依赖所有修改放到外部处理脚本和独立输出目录。如果已经冲突先用git stash暂存本地改动拉取后再仔细恢复不要直接git checkout -- .因为那会丢掉你所有的清洗代码。6. 进阶玩法用自定义脚本做作者风格向量与韵律特征提取当数据已经稳定入库常规检索满足不了你的分析需求时最值得投入的进阶方向是提取诗作的韵律特征和作者风格向量。一个非常实用的做法是把每首诗拆成“五言/七言”、“句数”、“押韵字位置”和“常用意象词频”这几项组合起来就能大体刻画一个作者的风格画像。我会写一个特征提取脚本用正则模版判断诗句字数节奏再用分词工具统计高频词import re def extract_rhythm_features(content): sentences content.splitlines() sentence_len [len(re.sub(r[。、\s], , s)) for s in sentences if s] pattern for l in sentence_len: if l 5: pattern 5 elif l 7: pattern 7 else: pattern X return { std_len: pattern, max_line_len: max(sentence_len) if sentence_len else 0, line_count: len(sentence_len) } # 假设从 SQLite 取到一首诗 sample_content 床前明月光\n疑是地上霜 print(extract_rhythm_features(sample_content))这段代码的运行结果会告诉你一首诗的句长模式比如“57 57”代表五言与七言交替。这个特征对判断古体诗和近体诗非常有价值。当你把整个 chinese-poetry 数据集都跑一遍特征提取再按作者聚合就能看到类似“李白更偏爱七言”、“杜甫五言和七言分布更均匀”这种量化结论。而且这种方法不依赖任何深度学习模型结果可解释性强非常适合做教学演示和快速数据报告。实际执行时为了提速我会把特征提取结果直接写回 SQLite 的独立字段或单独一张poem_features表这样后续查询不需要重新计算。还要注意一点诗正文中的“兮”字和“之”字会影响句长判断必须在正则替换阶段把它们纳入忽略列表否则刻意仿楚辞风格的诗会被错误识别为杂言。最后说一个我的个人习惯每次跑完新的分析都会把输出文件按日期后缀命名绝不覆盖上一轮结果这样回头看数据变化时还有后悔药可吃。希望这些方法和避坑经验对你有实际帮助。本文还有配套的精品资源点击获取