简介:在数据密集型应用开发中,关系型数据库依然是处理结构化数据的基石。合理的数据建模能有效组织实体关系,而索引与全文检索则直接决定查询性能。以中华古诗词数字化场景为例,构建一个包含诗人、朝代、诗词及附属信息的数据库,需要统筹表结构设计、数据清洗、权限分配与性能优化等环节。本文基于MySQL实战,详细拆解了从需求分析到表关系建模、从字符集处理到全文索引调优的完整路径,并探讨了达梦/人大金仓迁移与向量数据库扩展方向,为古籍数字化爱好者提供了一套可复用的工程实践方案。 做古诗词数据库这件事,我是认真的。从最开始只是想给学生做个诗词检索工具,到后来一步步陷入数据建模、编码转换、权限控制、查询优化这些细节里,前后折腾了大半年。今天把整个项目的来龙去脉、表结构设计、数据清洗流程、权限方案、性能优化以及各种踩坑记录都整理出来,给要做数据库课程设计、古籍数字化、或者想自己搞一个诗词检索系统的朋友做个参考。这篇文章覆盖了从零开始搭建一个中华古诗词大全数据库的完整路径,内容有点长,但每一段都是实际操作中磨出来的。
1. 项目缘起与整体设计思路
1.1 为什么需要一个专门的古诗词数据库
在动手之前,我认真想过这个问题:网上现成的诗词库那么多,直接拿来用不就行了?但实际上,当你真正开始做的时候就会发现,大多数公开数据源都存在几个痛点:格式不统一、缺字段、作者信息不全、没有平仄标注、缺少赏析内容、更是很少有序号唯一的主键约束。如果只是拿来查一两首诗词,这些都不是问题,但如果你想做一个完整的检索系统、诗词学习App、或者对接人工智能做诗词分析,这种原始数据根本没法直接用。
我当时的真实需求是这样的:要给一个古典文学学习平台提供后端数据支撑,平台需要支持按诗人检索、按朝代筛选、按格律分类、按关键字搜诗句,还需要对诗词做赏析和翻译。这个需求拆下来,就已经不是一个简单的文本文件就能解决的了,必须落到数据库层面,建立结构化的表关系。
另外一个动力来自教学场景。很多计算机专业的学生做数据库课程设计,选来选去都是图书管理、学生选课,做烂了。古诗词数据库算是一个既有文化内涵又不失技术深度的课题,既能练到三范式设计、事务处理、权限分配,又能顺便学学全文检索和编码处理。这个项目做完之后,我发现所有标准数据库课程的知识点几乎全都覆盖了。
1.2 核心设计理念:先定边界,再建模型
设计一个数据库最忌一上来就建表。我做这个项目的第一个原则就是先把边界定清楚:诗词数据包括哪些实体?它们之间的关系是什么?哪些数据必须有,哪些只是锦上添花?
我用了一个非常简单但有效的方法,把需求写在一张便签上。诗词相关的实体,朴素地想至少包括:诗人、朝代、诗词正文、诗名、格律分类、赏析、注释、翻译。其中诗人隶属于朝代,诗词归属于诗人,赏析、注释、翻译都是诗词的附属信息。这种一对多的关系非常清晰。
第二个原则是宁可多拆表,不要全都塞在一张表里。有些公开数据源把诗词正文、注释、赏析全都存在一个字段里,乱七八糟地用分隔符隔开,当时看着省事,后面查询的时候简直是灾难。我见过有人把作者的朝代直接冗余在诗词表里,查询是方便了,但一旦某个朝代的名称规范需要调整,就得更新几百上千条记录,典型的不符合第三范式。所以我坚持把诗词、诗人、朝代、赏析、注释这些拆成独立表,用外键关联,虽然在初期增删改查会稍微麻烦一点,但对后续扩展和维护来说,收益大得多。
第三个原则是关于编码与格式的。古诗词里生僻字多、繁体字多、异体字多,存储层面如果不提前处理好,后面全是乱码。这个我在后面专门用一节细说,但设计的第一天就必须把字符集和排序规则定下来,越往后改动代价越大。
1.3 技术选型:传统关系型数据库依旧是首选
做这种结构化程度极高、关系明确的数据,关系型数据库是毫无疑问的首选,我用的是MySQL 8.x。原因不外乎这几点:第一,生态成熟,网上资料多,遇到问题不至于卡死;第二,InnoDB引擎支持事务和外键,对保证数据一致性非常重要;第三,MySQL的全文索引对诗词正文的检索支持很友好,后面做关键字搜索不用另起炉灶。
也有朋友建议我上NoSQL或者全文检索引擎,比如Elasticsearch。但仔细想想,诗词数据库的数据量其实并不大,即使收录五万首唐诗、两万首宋词,也就是几十万条记录的量级,MySQL配合合理的索引完全能扛住,没必要为这种量级引入一套额外的搜索集群。当然,如果你要做的是基于海量诗词数据的应用,比如语义搜索、跨语言的诗词灵感生成,那确实可以再挂一个向量数据库做补充,这个我在后面扩展应用的部分单独讲。
2. 表结构设计与数据建模详解
2.1 诗词、诗人、朝代三张核心表怎么建
先看核心的三张表。第一张是朝代表,字段很简单,就是朝代ID和朝代名称,里面主要包含唐、宋、元、明、清这些主要时期,同时也收录了先秦、两汉、魏晋南北朝这些早期时段,一共十几个条目。这张表的存在意义主要是为了后续按朝代筛选诗词,以及为诗人表提供朝代归属。
第二张是诗人表,我设计的字段包括诗人ID、姓名、朝代ID、字号、生卒年、籍贯、简介。其中生卒年我用的是VARCHAR类型而不是DATE,因为很多古代诗人的生卒年本身就模糊,比如"约公元712年—公元770年",这种表述没法用日期类型严格表达。简介字段放的是诗人的人物生平概述,后面可以做专门的人物详情页面。
第三张核心表就是诗词表,这是整个数据库的灵魂。我最终确定的字段包括:诗词ID、诗名、诗体、作者ID、朝代ID、正文、注释、翻译、赏析、创作背景、是否完整、数据来源。这里最关键的字段是正文,我用的是TEXT类型,一首长诗如《琵琶行》,六百多字完全能装得下。诗体字段用来标记五言绝句、七言律诗、词牌名、乐府诗这些分类。是否完整这个字段非常有价值,因为好多流传下来的古诗词只有残句,没有完整版本,标记清楚之后,使用者可以自由选择是否展示不完整的诗词。
外键方面,诗词表关联诗人表和朝代表,诗人表关联朝代表。这样设计之后,一个完整的查询链路就是:通过朝代定位诗人,通过诗人关联到诗词,再通过诗词ID找到对应的注释、翻译和赏析。整个结构清爽明了,符合第三范式的要求。
2.2 附属表:赏析、注释、翻译为什么不合并
很多人会问,赏析、注释、翻译为什么不直接当作字段塞进诗词表里?这样查询的时候一次就能拿出来,多方便。我一开始也这么干过,但很快发现几个问题。
首先是数据更新的灵活性。赏析文字经常会因为版本来源不同、校勘结果不同而需要修改,如果合并在一张大表里,每次修改赏析都要锁定整行数据,后续如果再增加多版本赏析(比如不同学者的解说),这张表的结构就要大改,非常麻烦。
其次是查询效率。如果一张表里全是TEXT字段,一次查询可能就把好几MB的数据读出来,即使你只需要诗词正文,也不得不连带读取那些大字段,导致性能白白浪费。
所以我最终把赏析、注释、翻译各自拆成了独立表。赏析表包括赏析ID、诗词ID、赏析内容、作者、来源;注释表包括注释ID、诗词ID、字词、释义、拼音;翻译表包括翻译ID、诗词ID、译文内容、译者、翻译风格。每张表都通过诗词ID建立外键关联。这样设计之后,页面要展示什么内容就按需查询对应表,首页列表只需要查诗词表本身,点击详情再懒加载拉取附属内容,性能非常友好。
2.3 索引设计的实战心得
索引这块是我反复调整最多的部分。建表初期,我给所有可能作为查询条件的字段都加了索引,结果发现有些索引几乎没被用到,反而拖慢了写入速度。后来通过分析慢查询日志,才把索引策略收敛下来。
目前最核心的索引是三个:第一个是诗词表的作者ID索引,所有按诗人查诗词的操作都走这个索引;第二个是朝代ID索引,按朝代做筛选时用;第三个是标题的普通索引,用于按诗名精确搜索。正文的全文索引我单独加的是FULLTEXT类型,配合MySQL的ngram解析器,能支持中文分词搜索,这个在按关键词检索诗句的时候非常香。
需要特别提醒的是,不要给TEXT类型的字段加普通B-Tree索引,数据库根本没法只对TEXT前缀做有效排序,索引建了也是白建,只会白白占用磁盘空间。全文索引是TEXT字段的正确归宿。
3. 数据采集、清洗与入库实操
3.1 数据来源选择与版权问题
古诗词本身作为古代文献,是公共版权资源,这一点没有任何问题。但要注意的是,很多现代网站对古籍做了标点、校勘、注释和翻译,这些整理成果是受著作权保护的。所以我的数据来源策略是优先使用古籍原典数字化项目,比如中华经典古籍库、国学大师、古诗文网等公开整理的资源。
实际采集的时候,我没有一上来就写爬虫,而是先用了几种比较靠谱的方式拿到初始数据。一部分是从一些开源项目里找到的JSON格式的诗词数据,比如GitHub上有很多爱好者维护的"Chinese-poetry"项目,数据量在几十万首这个量级,质量虽然有参差,但胜在覆盖面广。另一部分是针对重点诗人的数据,我做了人工核对和补全。如果你是自己做学习项目,用公开的开源数据集完全没问题,但如果是商业用途,一定要仔细确认数据来源的授权情况。
如果你需要采集特定网站的数据,我的建议是:先看robots协议,控制请求频率,不要给目标网站造成压力。另外必须做数据合法性验证,至少要校验诗词正文是否为空、是否包含异常字符、长度是否合理。这个项目里我加了几道清洗流程,把常见的全角半角混乱、HTML标签残留、前后空格、换行符异常都清理掉了。
3.2 清洗脚本里的几个关键处理
清洗是整个项目最磨人的一步,没有之一。直接用原始爬下来的数据往里灌,后半辈子都要在数据修复中度过。我写了一个Python脚本,分几步来处理。
第一步是统一字符集和繁体转换。我遇到的最大坑是来源数据里简体繁体混杂。有些站点是繁体录入,有些是简体录入,还有同一个网页里正文是简体、注释是繁体的情况。最终的解决方案是引入OpenCC这个开源库做繁简转换,统一转成简体字存储。当然,如果你要做古籍研究,可能需要保留繁体版本,那就是另一种设计思路了。
第二步是去除噪音。最典型的是HTML标签残留,比如"
"、"
"这种。我用正则表达式全局清理。还有全角英文字母、奇怪的空白字符、连续多个换行符,这些都要处理干净。
第三步是规范化格式。诗词正文的格式处理我是这么做的:每句诗词单独一行,用换行符分隔,避免把所有诗句挤在一段里。这样的存储格式方便前端直接渲染,也方便后续做平仄分析和格律校验。格式统一之后,按诗人分组的数据在导入时会有更好的体验。
3.3 批量入库事务与数据校验
数据清洗完毕之后,剩余的就是批量入库环节。我用的是INSERT批量语句和事务组合。把几千条诗词通过一个事务进行插入,好处是如果中途报错,可以整体回滚,不用怕留一堆半成品数据。
入库之前要做的校验包括:必填字段是否为空、作者ID是否存在于诗人表、朝代ID是否存在于朝代表、诗词正文长度是否小于TEXT上限、是否存在重复数据。重复数据的检测我采用的是对诗名和正文做MD5哈希,通过哈希值比对来识别完全相同的诗词记录。这个效率很高,虽然可能把同一首诗的不同版本也判为重复,但作为第一道去重筛选已经够用了。
入库完成之后还有一个重要动作是做统计验证。比如对比源数据中诗人的数量、诗词的数量,以及诗歌按朝代的分布情况,确保导入没有大量丢失。这个项目最后入库唐诗五万五千余首、宋词两万一千余首、其他时期诗词若干,总计接近十万首,基本覆盖了常见传播的经典作品。
4. 权限管理、安全问题与数据库兼容性
4.1 多用户分级权限设计
如果数据库要开放给团队使用,权限设计是绕不开的一环。我的方案是创建三类用户角色:管理员、编辑、只读访客。
管理员拥有所有权限,可以创建和删除数据库、管理用户账号、导入导出数据。编辑角色可以增删改数据,但不能修改表结构,不能删除数据库。只读访客只有SELECT权限,只能查询和检索。
在MySQL中实现这个控制原理上就是GRANT语句的精细分配。管理员用GRANT ALL PRIVILEGES,编辑用GRANT SELECT, INSERT, UPDATE, DELETE ON 诗词库.*,只读访客则只需要GRANT SELECT。为了避免误操作,我还给编辑和访客的默认数据库设置做了限制,只允许他们操作诗词库这一个库,其他库一律不授权。
这套权限体系虽然简单,但实用性非常高。实际运行中,编辑角色负责增补和修正数据,访客角色给前端应用使用,管理员做维护,各司其职,谁也碰不到不该碰的地方。
4.2 SQL注入、批量操作安防
数据库安全方面,SQL注入是最常见的风险点。虽然诗词数据库本身不是什么高价值目标,但一旦通过这个入口被拿到数据库权限,连带着服务器上的其他东西也可能遭殃。
我采取的防护措施是:所有外部传入的参数一律使用预处理语句,无论是JDBC还是Python的MySQL驱动,都用参数化查询,坚决不用字符串拼接SQL。这里分享一个我见过的真实反例:有人在查询界面直接拼接用户输入的诗名,结果用户输入带单引号的字符串,SQL直接报错甚至可能被注入恶意代码。用参数化查询之后,这个问题从根上就解决了。
另外,对所有外部查询接口设置超时和限流,避免因为某个查询太复杂导致数据库被拖垮。诗词数据库虽然量级不大,但一个不带索引的模糊查询全表扫描起来,照样能把CPU打到100%。
4.3 从MySQL到达梦、人大金仓的迁移经验
因为项目后期需要适配国产化环境,我做了从MySQL到达梦数据库和人大金仓的迁移实验。这一步也踩了不少坑。
达梦数据库是国内非常有代表性的一款关系型数据库,兼容MySQL的很多语法,但并不是无缝迁移。主要工作集中在数据类型转换、自增主键的语法差异、索引命名策略这些方面。比如MySQL的AUTO_INCREMENT在达梦中要改成IDENTITY,部分TEXT类型可能需要转为CLOB,有些MySQL函数在达梦里也没有对应的实现,需要手动改写。
人大金仓基于PostgreSQL内核,迁移逻辑类似,但同样需要处理语法兼容性问题。从实操角度建议,迁移之前先做字段类型映射,写一个对照表逐项检查,同时要特别关注不同数据库对空字符串和NULL的处理策略,这是最容易被忽略但又影响数据一致性的坑。
如果你只是做单机个人项目,不建议一开始就选国产数据库,开发调试的效率比MySQL还是差一些。但如果项目明确要部署到信创环境,那么迁移基本功必须有,否则后面会非常被动。
5. 查询优化、全文检索与常见业务场景SQL
5.1 经典查询SQL写给自己看的备查手册
下面列几个高频查询场景的SQL写法,都是我实际项目中调试过的。
按诗人查其全部诗词:
SELECT p.id, p.title, p.content FROM poems p INNER JOIN poets a ON p.poet_id = a.id WHERE a.name = '李白' ORDER BY p.id;按朝代统计诗词数量:
SELECT d.name, COUNT(p.id) AS poem_count FROM dynasties d LEFT JOIN poets a ON d.id = a.dynasty_id LEFT JOIN poems p ON a.id = p.poet_id GROUP BY d.id ORDER BY poem_count DESC;按关键字搜诗句,走全文索引:
SELECT p.id, p.title, p.content FROM poems p WHERE MATCH(p.content) AGAINST('明月' IN NATURAL LANGUAGE MODE) LIMIT 20;查询某一首诗的完整信息(含作者、朝代、注释、赏析):
SELECT p.title, po.name, d.name, p.content, n.note_content, s.appreciation_content FROM poems p JOIN poets po ON p.poet_id = po.id JOIN dynasties d ON po.dynasty_id = d.id LEFT JOIN notes n ON p.id = n.poem_id LEFT JOIN appreciations s ON p.id = s.poem_id WHERE p.id = 10086;如果你用的是达梦数据库,语法会略有差异,但基于标准SQL的核心逻辑一致。只要表结构设计合理,跨数据库改写SQL的工作量并不会太大。
5.2 性能压测与慢查询优化
建好索引之后,我并不放心,专门做了性能压测。用三万多条诗词数据模拟高频查询场景,方法是写一个多线程脚本,开到50个并发线程,每个线程循环执行查询,观察数据库的响应时间和QPS。
实测下来,不带全文索引的模糊查询,比如LIKE '%明月%',在双核四线程的虚拟机上,平均响应时间是1.8秒,慢得离谱。加了FULLTEXT全文索引之后,同样的查询条件平均响应时间降到了30毫秒以内,提升了近60倍。这个对比说明了一个道理:在MySQL里做中文字段的模糊搜索,全文索引几乎就是唯一的正规解法,前提是你要用对ngram解析器。
关于ngram的配置,需要在MySQL配置文件里设置:
[mysqld] ngram_token_size=2设置为2,表示按两个字符作为一个分词粒度,基本能适配中文检索习惯。如果设成1,索引体积会暴涨,检索噪音也会明显增大;设成3或更高,短的词语就搜不出来了。具体选择哪种粒度,取决于你的搜索场景,但古诗词检索普遍建议2。
5.3 数据备份与恢复策略
古诗词数据库虽然不算什么特别重要的生产系统,但我还是做了每日自动备份,用的方案非常朴素:每天凌晨用crontab执行mysqldump,把整个诗词库导出成SQL文件,保留最近14天的备份,定期同步到异地存储。
0 2 * * * mysqldump -u backup_user -p'密码' poetry_db > /backup/poetry_$(date +\%Y\%m\%d).sql备份这步千万不要省。数据采集、清洗、入库花了那么多天,一次误删数据就能让你心态崩掉。我中间就经历过一次:在调试一个删除脚本时,WHERE条件少写了一个字段,直接删掉了两千多条诗词数据,幸好前一天有自动备份,恢复起来也就是一条命令的事。从那之后,我对备份这件事再也不敢马虎。
6. 从数据到应用:扩展生态的几个方向
6.1 全文检索与向量数据库的结合
关系型数据库能解决80%的日常查询需求,但如果你想让用户用自然语言搜索古诗词,比如输入"描写月亮的诗"、"表达思乡的句子",传统SQL就不再适用了。这时候就要考虑上向量数据库。
我的扩展方案是把诗词正文切分为段落或句子,用文本嵌入模型转换成向量,存入专门的向量数据库,再通过语义相似度计算来实现语义搜索。这个方案在RAG应用里非常常见,也是目前大语言模型落地的热门组合方式。
具体架构上,MySQL仍然是源数据的事实担当,所有结构化查询、权限管理、事务更新都走MySQL。向量数据库作为补充层,只负责处理语义检索请求。两层各司其职,数据同步通过定时任务从MySQL抽取数据、生成向量、写入向量库。这样既不会影响核心数据的稳定性,又能让应用具备智能检索能力。
6.2 提供REST API供前端调用
做这个事情的初衷是给诗词学习平台做数据支撑,所以后端必然要提供一个API服务。我选择用Spring Boot 3搭建了一个轻量服务,暴露几个REST接口:查询诗词详情、按诗人搜索、按朝代筛选、按关键字搜索、获取随机一首诗词。每个接口都做了分页和参数校验,防止恶意调用。
这层API的好处在于,前端完全不用关心数据库的表结构和SQL细节,只需要和JSON打交道。另外,因为我做数据库全程用的是MySQL,团队里如果有其他人用其他语言写前端,联调起来也不会遇到障碍。数据库本身和API的边界越清晰,整个项目越容易协作。
6.3 给数据库做一个管理后台
没有一个趁手的可视化管理工具,日常维护数据库就会比较痛苦。命令行当然强大,但对非技术人员并不友好。我给这个项目配了一个简单的管理界面,能完成检索诗词、修改赏析、查看统计图表这些基本操作。技术上就是用JSP加Servlet做的传统Java Web应用,虽然谈不上漂亮,但胜在简单稳定。
如果你不喜欢自己写管理界面,还有一些现成工具可以用。比如DBeaver,开源免费,支持多种数据库,界面直观,对新手相当友好。如果要管理SQLite格式的诗词数据库,DB Browser for SQLite是一个非常轻量的选择。国产数据库基本也有自己的管理工具,比如达梦有达梦管理工具,人大金仓有KSQL。选择哪款工具不重要,重要的是你要有至少一个顺手的数据查看器,否则调试SQL的时候效率会非常低。
7. 常见问题与排查技巧实录
7.1 编码乱码问题:一篇完整排查案例
古诗词数据库最常见的坑就是乱码。我在数据导入阶段遇到过一次大面积乱码,所有繁体字变成了问号,带生僻字的诗名全成了"????"。排查过程是这样的:
首先排除客户端问题,在命令行里用SELECT查一条记录,发现依然乱码,说明问题出在数据库或连接层。接着查数据库的字符集设置,发现表确实建成了utf8mb4,理论上不该乱码。继续追,发现是连接串没指定字符集,JDBC的URL里面少了一个characterEncoding=utf8参数。加上之后,重新导入数据,乱码问题解决。
这次经历让我养成了一个习惯:所有和数据库打交道的入口,包括连接字符串、控制台、导入脚本、API返回头,都必须显式声明utf8mb4,一个地方漏掉,乱码就随时可能冒出来。
7.2 并发锁与死锁的处理经验
用户在短时间内大批量导入数据时,会同时开启多个事务,可能会出现锁等待甚至死锁的情况。有一次我同事导数据,一个事务里先改了诗词表,又改了赏析表,另一个事务正好顺序相反,两边互相等对方释放锁,过一会儿MySQL就报死锁了,把其中一个事务直接回滚。
解决的思路有两个层面。第一,规范事务顺序,所有事务都按同一个顺序访问表,尽量降低死锁概率。第二,设置合理的锁等待超时时间。在InnoDB里,可以用innodb_lock_wait_timeout参数控制等待时间,默认50秒太长了,我把这个值调到了5秒,如果出现锁竞争可以快速报错,及时止损,而不会把应用卡成僵尸。
7.3 数据同步与增量更新技巧
诗词库不是一成不变的,经常要补充新校勘的版本、修正历史记录的讹误。如果每次都全量导入,处理量既大又容易引入问题。我后来采用了一种简单的增量更新策略:在诗词表里增加一个更新时间字段,插入或修改记录时自动更新这个字段,导入程序只处理最近一次导入之后有变更的数据,用外部数据的来源ID和更新时间做比对,有变化的才更新。
这套机制配合定时任务,基本实现了自动化同步。虽然用不上那些复杂的数据同步工具,但对于诗词库这种量级和更新频率,是恰到好处的解法。
7.4 面试中关于这个项目的提问思路
做数据库这块同时也是一个很吸引人的面试项目。我在面试里遇到过与这个项目相关的不少问题,简单整理一下供大家参考:
- 为什么选择关系型数据库而不是NoSQL?回答思路:数据关系固定且清晰、需要事务支持、无高性能扩展需求。
- 如何解决大字段存储和查询效率的矛盾?回答思路:拆分附属表、懒加载、避免大字段非必要读取。
- 怎样保证数据清洗的质量?回答思路:多层校验机制、去重策略、人工抽查样本、统计分析。
- 全文索引为什么比LIKE快?回答思路:倒排索引的原理、多字符分词、避免全表扫描。
- 如果要做语义搜索,你打算怎么设计?回答思路:向量化、向量数据库、RAG架构,MySQL与向量库分层协同。
这些问题其实没有标准答案,但每个问题背后都在考查你做的事情有没有深度、有没有思考过取舍。只要项目是亲手做完的,回答起来会非常自然。
8. 一些实在的建议
最后再分享几个我做了这个项目之后的经验。第一,做数据型项目,时间分配上不要只想着写代码,清洗数据往往占掉一半以上的工时,越早开始处理数据,后面的节奏就越从容。第二,数据库表的字段宁可一开始多留几个冗余字段,也不要后面频繁ALTER TABLE,早期想清楚每一个字段的必要性,后面能省下大量折腾的时间。第三,备份真的不要嫌麻烦,一次误操作造成的损失,远超你每天备份花掉的那两分钟。
如果后面有余力,我打算在这个基础上接入大模型的诗词问答能力,把知识图谱和诗词库结合起来,让用户不只是搜索,还能问出诸如"王维的诗里哪些提到了禅意"这种复杂问题。这个方向也是一条挺有意思的技术路线,感兴趣的话后面我们接着聊。
本文还有配套的精品资源,点击获取