尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从文本到SQLite:构建唐诗三百首结构化数据集与查询实践

发布时间:2026/9/25 14:31:31

资讯中心
01
ARTICLE

从文本到SQLite:构建唐诗三百首结构化数据集与查询实践

从文本到SQLite:构建唐诗三百首结构化数据集与查询实践
简介这份数据集以「唐诗三百首」为主题整理收录320条经典唐诗的结构化记录覆盖诗题、作者、正文等常见字段适合中文学习者、文学研究者、数据分析师以及后端开发者在文本挖掘、诗词应用、数据库课程设计等场景中直接使用。压缩包共4个文件分别提供JSON、CSV、SQL、XLSX四种格式JSON便于程序间灵活交换CSV适合表格处理与机器学习预处理SQL脚本可直接导入MySQL等关系型数据库XLSX则方便非技术用户快速浏览筛选四种格式覆盖了常见使用路径。整个压缩包仅141KB轻量易下载。目前已有1449人学习下载口碑实用尤其适合需要快速获取标准中文古诗语料用于教学演示、接口测试或数据建模的初学者与进阶开发者。拿到手即可按需选用对应格式无需重新爬取或手工整理能有效节省数据准备时间直接聚焦后续分析、算法验证或应用开发是一份高性价比的古典诗歌文本数据集。1. 为什么我现在还会把《唐诗三百首》做成一款数据库数据集如果你只是上网搜一个现成的 txt 来背诗那确实不需要数据库。但如果你在做数据库课程设计、练 SQL 查询、或者想搭一个能按作者、按意象、按韵脚检索的古诗词检索工具你会很快发现网上流传的《唐诗三百首》文本大多来源不明、编码混乱、断句随缘拿来做数据集基本是给自己埋雷。我几年前接过一个课程设计需求学生拿到的原始数据是一份从古诗词站点抓下来的网页转文本三百多首诗里混着编者按、注释和广告残留清洗花了整整一个晚上。从那之后我的习惯就变了先把《唐诗三百首》整理成一份结构化的数据库数据集再谈查询和应用。这个方向适合三类人——做课程设计的学生、想练手 SQL 和 Python 的开发者、以及做中文文本检索实验的研究者。它能解决的核心问题就一个让三百首诗的检索、统计、筛选变成几分钟内可以完成的事。2. 从 txt 到表结构把三百首诗拆成可查询的字段2.1 先搞清楚《唐诗三百首》的原始文本长什么样网上流传的《唐诗三百首》文本来源复杂常见的形态有三种第一种是带卷次结构的纯文本开头是「卷一」或「五言古诗」下面逐首列出标题、作者、正文第二种是网页爬虫抓下来的 HTML 转文本每首诗之间可能残留「上一篇」「下一篇」这类导航文字第三种是 ePub 或 PDF 导出的文本排版错乱、繁体字与简体字混用。我拿到原始文件后的第一个动作不是写正则而是先打开文件看前面的三十行确认它的编码、换行规则和分隔方式。这一步在操作上很短但能省掉后面大量的返工。确定了文本形态之后再定清洗方案。以最常见的「标题 作者 正文」三段式为例一首诗在文本里大致长成这个样子标题独占一行作者独占一行从第三行开始到空行之前是正文。但《唐诗三百首》有个特例五言绝句和七言绝句可能两首连排中间只空一行或者正文里混入了「唐李白」这样的括号前缀。整理这块时我一般不看网上的现成脚本而是自己写一个针对格式的解析规则因为不同来源的断行方式差异不小现成脚本往往要二次修改。2.2 用 Python 把原始文本切分成结构化数据下面是我处理这类原始文本时常用的拆分脚本核心思路是用「空行 标题行特征」定位每首诗的开始位置然后把标题、作者、正文切出来最后统一写出 CSV。这里不以任何现成包为前提只需要 Python 标准库就能跑完。import re import csv SOURCE_FILE tangshi_raw.txt OUTPUT_CSV tangshi_clean.csv def parse_text(raw: str): lines [line.strip() for line in raw.splitlines() if line.strip()] poems [] i 0 while i len(lines): title lines[i] # 标题行的特征长度较短且不以常见标点结尾 if not 1 len(title) 12: i 1 continue author body_lines [] i 1 # 下一行可能是作者也可能是直接进入正文 if i len(lines) and 1 len(lines[i]) 6: author lines[i] i 1 while i len(lines): nxt lines[i] # 遇到短行且像是新标题时停止收集正文 if len(nxt) 12 and not nxt.endswith((。, , , )): break body_lines.append(nxt) i 1 poem_text .join(body_lines) if title and poem_text: poems.append({title: title, author: author, body: poem_text}) return poems with open(SOURCE_FILE, encodingutf-8, errorsignore) as f: raw f.read() poems parse_text(raw) with open(OUTPUT_CSV, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[id, title, author, body]) writer.writeheader() for idx, p in enumerate(poems, 1): writer.writerow({id: idx, title: p[title], author: p[author], body: p[body]}) print(f解析完成共 {len(poems)} 首诗)这段逻辑的核心在while循环的判断条件里我把「短于等于 12 个字且不以句末标点结尾」的行视为下一首诗的标题。之所以用这个规则是因为《唐诗三百首》的标题普遍是《感遇》《送别》这类不超过四个字的短题而正文末行通常以句号、问号或分号收尾两者特征差异明显。作者行则根据长度判断超过六个字的行基本不可能是作者。这个方案的参数依赖原始文本的排版规范如果换一个来源的文本建议先跑一遍并打印所有被切出来的标题人工核对。编码上我统一用utf-8-sig写 CSV这样用 Excel 打开时不会出现中文乱码后面导入数据库时也少一层编码问题。2.3 建表方案单表够用三表更规范数据拆完下一步是决定怎么存进数据库。常见做法有两种一种是把全部字段塞进一张poems表字段包括id、title、author、dynasty、body、volume另一种是拆成poets表和poems表诗人信息单独存放。对《唐诗三百首》这种体量的数据集单表完全够用三百多条记录在 SQLite 里查询是毫秒级根本不需要为了范式而故意拆表。但如果你想把数据集做得更规范或者后续打算扩充到《全唐诗》那按作者拆表是更稳的方案。建表时我一般会在 SQLite 里这样写CREATE TABLE poems ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, author TEXT, dynasty TEXT DEFAULT 唐, body TEXT NOT NULL, volume TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_poems_author ON poems(author); CREATE INDEX idx_poems_title ON poems(title);字段类型上title和author用 TEXTid用 INTEGER 主键。由于古诗场景没有复杂的数值运算不必用 VARCHAR(n) 来限制长度TEXT 在 SQLite 里更省事。索引方面author和title是查询高频字段各建一个普通索引就够了。body字段不要建索引因为对全文做模糊匹配时索引基本失效这个在后面讲查询时会说。注意逗号分隔的 SQL 语句在数据库工具里执行没问题但如果写在 Python 的sqlite3模块里建议用executescript而不是execute因为一条execute只能执行单条语句。3. 用增删改查玩转这批数据集导入、检索与常用 SQL 姿势3.1 从 CSV 导入 SQLite 的完整姿势上一步生成的tangshi_clean.csv还停在文件层面接下来的标准动作是把它装进 SQLite 数据库。用 Python 的sqlite3模块是直接的方式我一般不用命令行里的.import因为 CSV 字段里可能带引号和换行命令行导入的转义规则在这种数据上容易出问题。下面是常用的导入脚本import sqlite3 import csv DB_PATH tangshi.db CSV_PATH tangshi_clean.csv conn sqlite3.connect(DB_PATH) cur conn.cursor() cur.execute( CREATE TABLE IF NOT EXISTS poems ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, author TEXT, body TEXT NOT NULL, volume TEXT ) ) with open(CSV_PATH, encodingutf-8-sig) as f: reader csv.DictReader(f) rows [(row[title], row[author], row[body]) for row in reader] cur.executemany( INSERT INTO poems (title, author, body) VALUES (?, ?, ?), rows ) conn.commit() conn.close() print(f已导入 {len(rows)} 条记录)executemany是批量导入的关键比逐条execute快一个数量级而且能自动处理参数转义避免 SQL 注入和引号冲突。注意csv.DictReader会把表头映射成字典键如果第 2 章导出的 CSV 表头是id,title,author,body这里就要对应取row[title]、row[author]、row[body]。另外导入前一定要先清空表或使用CREATE TABLE IF NOT EXISTS否则重复运行脚本会插入重复数据。见过的翻车案例里十有八九是反复执行导入脚本导致数据翻倍这类问题很好排查但对新手来说确实容易忽视。3.2 五个高频查询从「数据躺在库里」到「用起来」数据导入后最直接的回报就是可以用 SQL 优雅地做统计和检索。以课程设计或日常练手为例我列几个高频查询场景。第一个是统计每位作者的收诗数量这条 SQL 能直接看出《唐诗三百首》里谁的作品最多SELECT author, COUNT(*) AS cnt FROM poems GROUP BY author ORDER BY cnt DESC LIMIT 10;第二个是全库模糊搜索。比如查「含有‘明月’的诗句」用LIKE配合通配符即可。但这里有一个值得注意的细节LIKE %明月%无法利用 B 树索引全表扫描三百条记录也很快可一旦数据量涨到三十万条性能就完全不同。这正是为什么前面说body字段不要建索引因为建了也白建SELECT title, author, body FROM poems WHERE body LIKE %明月%;第三个是「按作者 主题」的组合筛选例如查李白作品中带有「酒」字的诗句。SQL 层面的组合条件本身不复杂但它的意义在于展示了「结构化 模糊查询」的叠加效果这在纯文本里做是很别扭的SELECT title, body FROM poems WHERE author 李白 AND body LIKE %酒%;第四个是统计类查询比如每卷收诗数量、每种诗体的平均字数。这类查询适合拿来做数据集质量校验。如果发现某个卷次只有两首诗那大概率是文本分段出了问题SELECT volume, COUNT(*) AS cnt FROM poems GROUP BY volume ORDER BY cnt DESC;第五个是随机抽诗。在课程设计里做一个「每日一诗」模块核心就是一条随机排序查询。SQLite 的写法是ORDER BY RANDOM() LIMIT 1MySQL 则用ORDER BY RAND() LIMIT 1。这种查询在数据量小的时候没有性能问题但注意它同样不能用索引优化不适合搬到线上大表SELECT title, author, body FROM poems ORDER BY RANDOM() LIMIT 1;3.3 说好的增删改查查已到位剩三个也不能漏一篇数据库课程设计报告只写 SELECT 会显得单薄增删改查四个动作一般要齐活。INSERT 在前面导入脚本里已经出现过这里补一条思路如果你要手工录入一首新诗字段要写完整尤其是dynasty字段不要漏否则统计时会出现「默认唐」和「空值」两本账。UPDATE 的场景不多但常见于修正错别字或作者误标。比如发现「李白」被写成了「李百」一条语句解决问题UPDATE poems SET author 李白 WHERE author 李百;DELETE 要慎用。我见过有人写DELETE FROM poems;忘了加 WHERE 把整表清空的事后只能靠备份恢复。建议在日常操作里严格遵守两条纪律第一执行 DELETE 前先写一条相同 WHERE 条件的 SELECT 确认范围第二导入阶段不要直接在生产表上操作先建一张临时表验证数据再改名。MySQL 和 SQLite 在ALTER TABLE ... RENAME TO ...上的语法略有差异但基本思路一致留后悔药不留事故。4. 常见问题与避坑编码、断句和重复数据的三类血泪记录4.1 CSV 导入后中文乱码现象是数据库里能查到数据但中文全部变成了「锟斤拷」或者一堆问号。原因通常有两个原始 CSV 文件是 UTF-8 编码而你在导入时没有显式声明编码或者你没有给字段设置TEXT类型而是用了BLOB。更隐蔽的情况是在 Windows 上用 Excel 打开保存过 CSVExcel 会把编码改成 ANSIGBK再拿这个文件导入 UTF-8 数据库就必乱。解决办法是统一在 Python 侧用encodingutf-8-sig读取 CSV并且导入前就确认好数据库连接字符集。SQLite 不太挑字符集但 MySQL 需要显式设置SET NAMES utf8mb4;才保险。4.2 切分脚本把两首诗并成了一首现象是解析后统计出来只有两百九十多条记录而《唐诗三百首》全文应该是三百一十首左右不同版本有差异。打开数据看发现某些诗被拦腰截断又接到下一首。原因在于我的标题判断规则短行 不以句末标点结尾在遇到某些五言绝句时失效了因为上一首的末句恰好不是句号结尾而是问号或感叹号而我的断行条件只排除了句号、感叹号、问号和分号没有排除省略号。解决的办法是扩大排除集把省略号、破折号也加进去并且在解析后立即做一次「标题长度全部小于 8 且正文长度全部大于 20 字」的校验把异常记录挑出来手工核对。4.3 同一首诗出现了多条记录现象是《送元二使安西》在数据库里出现了两次一次作者是「王维」一次是「王維」。原因是原始文本来源不同一份是简体版一份是繁体版或半繁体版切分后混在同一张表里。这类重复对统计结果影响很大做「按作者统计」时王维的诗歌数量会虚高。解决思路分两层先做繁体转简体最简单的办法是在 Python 里用开源转换库统一转或者做一层「标题 作者 首句」联合唯一键来去重。SQLite 支持在创建表时定义UNIQUE(title, author, body)导入时配合INSERT OR IGNORE可以自动剔除完全一样的重复行但对繁简差异造成的「形近而实异」仍需先转换再导入。4.4 LIKE 查询与预期不符现象是查LIKE %月%时「月」字被查出来了但有一批含「明」的诗没被命中或者反过来查出一堆完全无关的记录。原因多半是原始文本里的标点符号是半角逗号和全角句号混用导致正文被切分成了很多片段某些「月」字恰好位于断行位置两个字段拼接顺序出错。我的做法是清洗阶段统一做一次全角/半角标点归一化把英文逗号、句号、问号全部替换成中文标点。这个操作放在解析之后、导入之前。另外LIKE默认是不区分大小写的但对中文没有意义这一条不算坑只是提醒你别在中文数据上对 LIKE 的大小写行为产生预期。4.5 数据库文件打不开或路径里带不出记录现象是 SQLite 文件在 Python 脚本里能查但换成数据库工具打开时看不到表或者报「file is not a database」。原因往往是路径写错了打开了同目录下的另一个同名文件或者是用sqlite3.connect创建数据库时忘记写后缀.db生成了一个无扩展名文件。这种情况在 Windows 上最隐蔽因为资源管理器默认隐藏扩展名两个文件看起来一样。解决方法是建立固定习惯在脚本开头打印DB_PATH的绝对路径导入后用PRAGMA integrity_check;做一次完整性检查。这条命令能快速判断文件是否被破坏也可以用来验证备份是否可用。5. 让数据集成作品全文检索、指标校验与课程设计场景5.1 用 SQLite FTS5 给「查诗句」加上全文检索如果只是用 LIKE 做模糊匹配数据量小没问题但你想做「输入一个词输出所有包含该词的诗句及其出处」这类检索时LIKE 的体验就一般了。SQLite 自带全文检索扩展 FTS5建一张虚拟表来承载body字段的索引查询速度和 LIKE 完全不在一个量级。做法是给诗集数据建一张 FTS 表导入时同步填充查询时用MATCH语法CREATE VIRTUAL TABLE poems_fts USING fts5(title, author, body); INSERT INTO poems_fts (title, author, body) SELECT title, author, body FROM poems; SELECT title, author, snippet(poems_fts, 2, 【, 】, …, 12) FROM poems_fts WHERE poems_fts MATCH 明月;snippet函数会从正文中抽出命中位置附近的一小段文字前后加上你指定的标记。这对做检索结果预览很有用。需要注意的点有两个FTS5 表与普通表是独立的源表数据更新后 FTS 表要同步更新另外MATCH默认是按分词和短语匹配中文分词效果有限短词搜索时不如 LIKE 直接但在长句和短语搜索场景下优势明显。5.2 用统计指标验证数据集质量查验数据集是否可用不能只靠肉眼下面这几个指标可以作为标准检查项。第一个是原始记录总数与权威版本比对第二个是body字段的平均长度如果某条记录正文少于 20 个字大概率是切分残缺第三个是author字段为空的比例正规数据里这个比例应该为 0第四个是「标题重复」的组数用来定位疑似重复数据第五个是「作者数量」唐诗三百首收录的诗人有七十余位偏差过大就说明作者字段有问题。把这些指标写成一段 Python 脚本每次清洗完数据自动跑一遍能省下不少人工核对时间。5.3 这套数据集在课程设计里怎么用如果你是在做数据库课程设计这套数据集几乎是现成的素材。前端可以做一个「诗人作品检索 每日一诗 主题词云」的简单页面后端接 SQLite查询就是前面写的那些语句足够覆盖「设计报告」里要求的增删改查和索引设计说明。想增加区分度可以在报告里讲清楚你为了清洗数据做了什么不如从文本清洗、繁简转换、断句修正、去重和导入校验这几个维度各写一小节。最后一件事是备份意识无论库有多小做完清洗就导出一份tangshi_clean.csv备份放在项目目录外这是你的后悔药。数据库文件删了可以重建原始清洗脚本丢了就只能从头再来。这是我做文本型数据集养成的习惯写在这篇笔记里希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。