ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

chinese-poetry 古诗词数据库:结构化 JSON 落地与检索实践

chinese-poetry 古诗词数据库:结构化 JSON 落地与检索实践 简介中华古诗词数据库chinese-poetry是一份面向开发者、文史研究者与传统文化爱好者的开源数据集旨在解决古典文集获取门槛高、纸质书籍难以随身携带的问题让使用者能以便捷的电子化方式检索与二次开发。资源以 JSON 格式分发收录 5.5 万首唐诗、26 万首宋诗、2.1 万首宋词及其他古典文集涵盖唐宋近 1.4 万位诗人与两宋 1.5 千位词人。压缩包共 2000 个文件以 1978 个 json 数据文件为主体另含 16 个 md 说明文档、4 个 py 脚本、1 个 js 与 1 个 txt整体约 91.18MB目录按诗人、朝代与篇目分卷组织便于按需加载。已有 818 人学习下载。读者可直接将其接入诗词检索、文本分析、NLP 训练或文化类应用开发省去繁琐的数据清洗与整理环节快速启动自己的项目。1. 中华古诗词数据库chinese-poetry 到底装了什么谁该把它跑起来如果你做过诗词类小程序、古文 NLP 语料清洗或者要给大模型喂一批高质量中文语料大概率绕不开 chinese-poetry 这个名字。它不是某个 App也不是一份官方文档而是一个把中华古诗词整理成结构化 JSON 的开源数据库项目。我第一次接触它是因为要做一个「飞花令」小工具当时以为随便找个诗词 API 就够了结果接口限流、字段残缺、繁简混乱折腾两天后翻到这个库才发现真正省事的做法是直接把数据落到本地用数据库增删改查的方式自己掌控。它解决的核心问题很朴素把散落在古籍、网页、扫描件里的诗词变成字段统一、编码统一、可直接被程序读取的数据。适合三类人做诗词类应用的开发者、做古文 NLP 的研究者、以及需要中文语料做检索或推荐实验的工程师。不适合只想调个接口、完全不想碰数据文件的人。下面我按「它是什么 → 怎么落地 → 坑在哪 → 怎么用得更狠」的顺序把这条链路讲透。2. chinese-poetry 的数据结构先看清 JSON 里到底有什么2.1 目录划分与文件组织这个库最直观的特点是按朝代和体裁分目录。常见做法是唐诗、宋诗、宋词、诗经、楚辞、论语、蒙学等各自成目录每个目录下再按作者或卷次切成多个 JSON 文件。这样切分的好处是单文件不会大到内存爆炸坏处是你得先遍历目录才能拼出完整数据集。我一般先做一件事把整个库 clone 到本地然后用脚本统计每个目录的文件数和总记录数。不要一上来就写业务代码先摸清数据规模否则后面建表、分页、索引全是拍脑袋。# 克隆到本地目录名按实际仓库为准 git clone repo-url chinese-poetry cd chinese-poetry # 统计各目录 JSON 文件数量与总大小 find . -name *.json | wc -l du -sh .逻辑说明find用来确认文件总量du看整体体积。参数上没什么可调的但要注意如果仓库带.git实际数据体积会比du显示的小。这一步的目的是让你对「要不要全量入库」有个判断——如果只是做唐诗检索就没必要把宋诗、蒙学全灌进去。2.2 单条记录的字段含义以唐诗为例一条记录通常包含作者、标题、段落正文、体裁、标签等字段。不同目录字段名会有差异这是最容易翻车的地方。我见过有人直接按唐诗的字段去解析宋词结果正文全空排查半天才发现字段名不一样。import json with open(唐诗/poet.tang.0.json, r, encodingutf-8) as f: data json.load(f) sample data[0] print(sample.keys()) print(sample.get(author), sample.get(title)) print(sample.get(paragraphs))逻辑说明先打印keys()确认字段名再取作者、标题、正文。参数上重点是encodingutf-8这个库全是中文用默认编码在部分系统上会直接报错。paragraphs一般是列表因为长诗会分多段入库时要决定是拼成一个字符串还是保留数组——我建议保留数组检索时再拼避免丢失结构。2.3 繁简与异体字的现实这个库的数据来源复杂繁简混用是常态。有的目录是繁体有的已经转成简体还有异体字。做检索时如果不统一用户搜「清风」可能搜不到「清風」。常见做法是入库前统一转简体或者建两个字段分别存原文和简体。我一般保留原文字段不动另加一个content_simple字段专门给检索用这样既不破坏原始数据又能保证搜索命中。3. 把 chinese-poetry 落到数据库建表、导入与检索3.1 选型SQLite 还是 MySQL如果只是本地做实验、做课程设计SQLite 足够单文件、零配置配合 DB Browser for SQLite 这类工具就能看数据。如果要对外提供服务、多人并发查就上 MySQL 或 PostgreSQL。热词里常出现「托管数据库服务」「数据库连接池」那是服务化之后才需要考虑的事本地阶段别过度设计。我的习惯是先用 SQLite 跑通全流程确认字段和检索逻辑没问题再迁到 MySQL。迁移时表结构基本不用改只改连接串和少量方言。3.2 建表语句与字段设计CREATE TABLE poems ( id INTEGER PRIMARY KEY AUTOINCREMENT, dynasty TEXT NOT NULL, author TEXT, title TEXT, content TEXT NOT NULL, content_simple TEXT, genre TEXT, source_file TEXT ); CREATE INDEX idx_author ON poems(author); CREATE INDEX idx_title ON poems(title); CREATE INDEX idx_simple ON poems(content_simple);逻辑说明dynasty标记朝代content存原文content_simple存简体用于检索source_file记录来源文件方便回溯。索引建在作者、标题、简体正文上因为这三类是最常见的查询入口。注意content不要建全文索引之前就盲目加数据量大时索引会拖慢导入先导入再建索引更快。3.3 批量导入脚本import json, os, sqlite3 conn sqlite3.connect(poetry.db) cur conn.cursor() def load_dir(path, dynasty): for name in os.listdir(path): if not name.endswith(.json): continue full os.path.join(path, name) with open(full, r, encodingutf-8) as f: try: records json.load(f) except json.JSONDecodeError: print(跳过异常文件:, full) continue for r in records: content \n.join(r.get(paragraphs, [])) cur.execute( INSERT INTO poems (dynasty, author, title, content, content_simple, genre, source_file) VALUES (?, ?, ?, ?, ?, ?, ?), (dynasty, r.get(author), r.get(title), content, content, r.get(tags, [None])[0] if r.get(tags) else None, name) ) conn.commit() load_dir(唐诗, 唐) load_dir(宋词, 宋) conn.close()逻辑说明load_dir遍历目录下所有 JSON逐个解析。json.JSONDecodeError的捕获很关键这个库个别文件格式不规整不捕获会直接中断整个导入。paragraphs用换行拼接成content。参数上content_simple这里先直接复制实际项目里应替换成繁转简函数的结果。tags取第一个作为体裁取不到就存 None。3.4 检索验证-- 按作者查 SELECT title, content FROM poems WHERE author 李白 LIMIT 5; -- 按正文关键词查 SELECT author, title FROM poems WHERE content_simple LIKE %明月% LIMIT 10;逻辑说明第一条验证作者索引是否生效第二条验证正文检索。LIKE %明月%在数据量大时会全表扫描如果检索频繁建议换成全文索引方案SQLite 用 FTS5MySQL 用全文索引或外部检索引擎。这一步是确认「数据真的能用」而不是导完就完事。4. 避坑与排查导入 chinese-poetry 时最容易翻车的五件事4.1 现象导入到一半报编码错误原因部分 JSON 文件不是标准 UTF-8或者含 BOM 头。解决读取时显式指定encodingutf-8-sig并在解析前用try/except包住跳过异常文件而不是整体中断。4.2 现象正文全是空的原因字段名不统一唐诗用paragraphs某些目录可能用别的键名。解决导入前先抽样打印每个目录第一条记录的keys()按目录分别写映射逻辑不要一套代码吃所有目录。4.3 现象检索「明月」搜不到含「明 月」的记录原因原文里有空格或标点分隔。解决入库时对content_simple做一次清洗去掉多余空白和标点检索时也对关键词做同样清洗保证两边一致。4.4 现象导入速度极慢原因每插一条就 commit 一次或者边导入边建索引。解决改成批量插入、最后统一 commit索引在导入完成后创建。数据量大时可以用事务包住整批插入速度能差出几十倍。4.5 现象数据库文件体积远超预期原因把.git目录、重复数据、无用字段全灌进去了。解决导入前明确只取需要的字段source_file这类调试字段上线前可以去掉或者单独存一张来源表。5. 进阶用法把 chinese-poetry 变成可检索语料服务数据入库只是起点。真正让这个库发挥价值的是把它接上检索和接口层。我一般会做三件事第一用 SQLite FTS5 或 MySQL 全文索引替换LIKE查询让「明月」「思乡」这类关键词检索从秒级降到毫秒级第二加一层简单的 HTTP 接口把作者、朝代、关键词作为查询参数暴露出去前端和小程序直接调第三针对飞花令这类场景按「诗句首字」建一个额外索引因为飞花令是按字接龙的普通全文索引并不擅长这种前缀匹配。-- SQLite FTS5 示例 CREATE VIRTUAL TABLE poems_fts USING fts5(title, content_simple, contentpoems, content_rowidid); INSERT INTO poems_fts (rowid, title, content_simple) SELECT id, title, content_simple FROM poems; SELECT p.author, p.title FROM poems_fts f JOIN poems p ON p.id f.rowid WHERE poems_fts MATCH 明月 LIMIT 10;逻辑说明FTS5 建虚拟表contentpoems表示外部内容表避免数据重复存储。MATCH是 FTS5 的检索语法比LIKE快得多。参数上要注意 FTS5 对中文分词支持有限默认按字切分短词检索没问题长句检索可能需要额外分词处理。验证方法很简单拿同一批关键词分别跑LIKE和MATCH对比返回条数和耗时。如果条数差异大说明分词或清洗逻辑有问题先对齐再谈性能。我踩过最深的一个坑是早期图省事把原文和简体混在一个字段里结果用户搜简体搜不到繁体原文搜繁体又搜不到简体数据来回改了三版表结构才理顺。后来我的习惯固定下来——原文永远不动检索字段单独维护清洗逻辑写成独立函数导入和查询共用同一套。这个习惯帮我省了太多后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表