拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

植物大全数据集导入与清洗实战:SQL/JSON/CSV处理指南

植物大全数据集导入与清洗实战:SQL/JSON/CSV处理指南

简介:该数据集是一份专门面向植物爱好者、园艺工作者及科研人员的多格式植物信息库。内容涵盖观花、观叶、多肉及流行植物等常见类别,每条记录包含植物名称、科属、生长环境、花期、花色与图片链接等关键字段,支持按属性进行筛选、查询与识别。资源共四个文件,压缩包约二点四兆,由SQL数据库、JSON元数据、CSV通用表格和XLSX电子表格组成,分别满足关系型查询、程序解析、跨平台交换及Excel可视化等不同使用需求。目前已有862人学习下载,既有现成的结构化数据可直接导入MySQL或其他分析工具,也可直接打开Excel查看和编辑。借助这套多格式组合,读者可快速搭建植物查询系统、制作花期花色对照表,或用于教学演示、科普展板及园艺设计参考,兼顾专业研究与兴趣学习,是植物数据落地应用的实用基础包。

1. 植物大全数据集:先搞清楚你拿到的是“数据库文件”而不是“图片包”

“数据库文件-植物大全数据集”是我被问得最多的一类资源:很多人以为下载后是几千张植物图片,打开发现是个几百 MB 的数据库文件,就不知道怎么下手了。实际上这份数据的价值不在图片,而在结构化整理好的植物名录——通常包含标准名、别名、科属、分类、用途、生长习性和图片路径等字段,文件格式常见 SQL、JSON、CSV 三种。它最直接的用途是给植物检索、科普展示、课程设计里的增删改查功能当底库,也能作为训练分类模型前的类别清单来源。适合几类人:急着给项目灌数据的开发者、做植物或鸟类识别方向课程设计的学生、想学数据库和数据集配合使用的新手。先别管图片,把数据库文件用对,这才是复现的第一步。

2. 表结构与三种格式:SQL、JSON、CSV 到底哪个适合你

拿到这类数据集,第一件事不是急着写查询,而是先认清数据结构。植物数据集的字段设计会直接决定你后面做检索、清洗、标注有多顺手。常见做法是把所有植物信息集中在主表里,字段大体一致,但版本之间会有少量差异。

2.1 主表结构与关键字段

一份植物大全数据通常会长成下面这样,不同版本字段名可能略有区别:

字段名类型说明
idINTEGER主键,唯一编号
nameTEXT植物标准名,比如“银杏”
aliasTEXT别名,多个之间一般用逗号分隔
familyTEXT所在科,比如“银杏科”
genusTEXT所在属,比如“银杏属”
categoryTEXT分类标签,乔木/灌木/草本/藤本
usageTEXT用途标签,如“药用”“观赏”“食用”
originTEXT原产地或主要分布区
habitTEXT生长习性,如耐寒、喜光、耐阴
image_pathTEXT图片路径,可能为空或仅存文件名
descriptionTEXT形态描述,常用于展示和检索摘要
created_atDATETIME记录插入时间

最容易让人迷惑的字段是 image_path。它可能存的是完整 URL、相对路径,也可能什么都没存。如果你打算做图片加载,得先确认这个字段到底存的是什么,别直接拼进前端。

2.2 SQL、JSON、CSV 三种格式怎么选

同一份数据,发布者通常会按不同格式压缩。三种格式各有适用场景,我的建议是:能直接用 SQL 的不要自己写解析脚本。

格式打开方式典型用途主要坑
SQLNavicat、MySQL、SQLite、命令行直接导入数据库,保留表结构和数据文件开头常带 DROP TABLE,执行前要注意
JSONPython json 模块、VSCode、各类编辑器给后端接口、小程序直接读取嵌套深度不一,别名和用途字段可能缺键
CSVExcel、WPS、pandas快速查看、数据清洗、数据库同步工具迁移中文编码容易乱,字段值里可能夹着逗号

如果你只是做演示项目,SQL 版是首选:导入后就能做增删改查。如果是要写代码读取,JSON 比 CSV 省事,因为 CSV 没有嵌入字段类型,数字、空值得自己猜。CSV 更适合用数据库同步工具做增量迁移,或者在 Excel 里人工核对数据。

2.3 数据质量与字段边界

别把这份数据当成绝对权威。我打开过几个版本,都有同样的问题:同一植物重复出现;别名里混着学名;usage 字段为空;科属命名不规范,比如“银杏科”和“银杏”混用。这类问题不影响看数据,但会影响做统计和训练。领域数据集的常态就是“能用但脏”,先把预期放低,后面清洗步骤会用到。如果后续要用它做检索系统或给识别类项目当基础数据,建议先按第 4 章的方式查一遍分布,再做清洗,否则跑到一半才发现字段是空的,会很被动。

3. 数据导入本地:从 SQLite 到 MySQL 的完整路径

了解结构之后,实际動手把数据导入本地。我一般建议新手先走 SQLite,因为它不需要安装服务,一个文件就是整个数据库。等确认结构和数据没问题,再迁到 MySQL 供多人或 Web 项目使用。

3.1 用 SQLite 最快打开

拿到 .db、.sqlite、.sqlite3 后缀的文件,直接用 Python 自带模块就能打开:

import sqlite3 db_path = "plant_database.db" conn = sqlite3.connect(db_path) cur = conn.cursor() # 查看这个数据库里到底有哪些表 cur.execute("SELECT name FROM sqlite_master WHERE type='table'") tables = cur.fetchall() print("表列表:", tables) # 统计主表的数据量 cur.execute("SELECT COUNT(*) FROM plant_info") total = cur.fetchone()[0] print("plant_info 总记录数:", total) # 抽样看一眼前 10 行 cur.execute("SELECT id, name, family, genus, category FROM plant_info LIMIT 10") for row in cur.fetchall(): print(row) conn.close()

这段代码里,sqlite_master 是 SQLite 的系统表,专门存表结构信息;connect 参数指向你的 db 文件路径。如果打开后找不到 plant_info,先执行第一条查询打印的表列表里找实际表名,再替换代码里的表名即可。COUNT 统计的是记录总数,LIMIT 10 控制抽样行数,这些是数据导入后最基础的三步验证。

3.2 往 MySQL 导入

如果你的项目是给多人用的 Web 系统,SQLite 的单机特性不够用,就得迁移到 MySQL。拿到 .sql 文件后,先建库再导入:

mysql -uroot -p -e "CREATE DATABASE plant_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" mysql -uroot -p --default-character-set=utf8mb4 plant_db < plant_database.sql

第一行创建名为 plant_db 的数据库,指定 utf8mb4 字符集,这样中文才存得完整。第二行把 SQL 内容导入指定库,--default-character-set=utf8mb4 是告诉客户端按这个编码解析文件内容。导入成功后可以用 mysql -uroot -p -e "USE plant_db; SHOW TABLES;" 验证。

需要注意的是,SQL 文件开头经常自带 DROP TABLE IF EXISTS,执行时会把已存在的同名表直接覆盖。你要是导入到正在用的数据库,先检查文件里的删表语句,别把一个演示库覆盖掉线上表。

3.3 从 JSON/CSV 重建表

有些版本只提供 CSV 或 JSON。这种情况没法直接“导入”,要先建表再灌数据。用 CSV 重建是最常见的:

import csv import sqlite3 conn = sqlite3.connect("plant_database.db") cur = conn.cursor() # 建表时先删掉旧表,避免重复 cur.execute("DROP TABLE IF EXISTS plant_info") cur.execute(""" CREATE TABLE plant_info ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, alias TEXT, family TEXT, genus TEXT, category TEXT, usage TEXT, image_path TEXT ) """) with open("plant_data.csv", encoding="utf-8-sig", newline="") as f: reader = csv.DictReader(f) rows = [] for r in reader: # 只取需要的字段,避免 CSV 里多出来的列影响入库 rows.append(( r["name"].strip(), r.get("alias", "").strip(), r["family"].strip() if r.get("family") else "", r["category"].strip() if r.get("category") else "" )) cur.executemany( "INSERT INTO plant_info (name, alias, family, category) VALUES (?, ?, ?, ?)", rows ) conn.commit() conn.close() print(f"导入完成,共 {len(rows)} 行")

这里我做了三件事:打开 CSV 用 utf-8-sig 编码,避免带 BOM 的文件在入库时把不可见字符写进第一个字段;用 DictReader 按列名取值,顺序错了也不会张冠李戴;插入前 strip 去空格,防止企业名称字段里夹着换行符。如果你手里的 CSV 用的是“\t”分隔,csv.DictReader 时加参数 delimiter="\t" 即可。JSON 版本逻辑类似,区别是取字段用 r["name"] 这类键访问。

4. 查询与清洗:把“植物大全”变成可复用的业务数据

数据导进去只是第一步。真正能用在项目里,需要把原始数据变成干净、可查询、可导出的数据。这一章按“查询 → 清洗 → 导出”三层来做。

4.1 高频查询场景:给数据做一次全面体检

先跑几条常用查询,看看数据里的科属分布和用途标签是否完整。下面的 SQL 在 SQLite 和 MySQL 里都能跑:

-- 按科统计植物数量,看数据覆盖范围 SELECT family, COUNT(*) AS cnt FROM plant_info GROUP BY family ORDER BY cnt DESC LIMIT 20; -- 查某科下的具体植物 SELECT name, genus, category FROM plant_info WHERE family = '银杏科'; -- 用途标签检索,模糊匹配 SELECT name, usage FROM plant_info WHERE usage LIKE '%药用%'; -- 找缺图片路径的记录,评估能不能做图库展示 SELECT COUNT(*) AS missing_image FROM plant_info WHERE image_path IS NULL OR image_path = '';

GROUP BY 按科分组统计数量,是判断数据分布是否均匀最直接的办法。LIKE '%药用%' 做模糊匹配,适合用途字段里混着多个标签的记录。统计 image_path 缺失数量,是为了早发现“这个数据集可能根本没有图片文件”的问题。跑完这几条,你对整份数据的完整度就有数了。

4.2 清洗脏数据:重名、缺失、编码错乱一起处理

清洗时最常见的三类问题:同一植物重复入库、别名和科属缺失、中文乱码。处理顺序有讲究,先清理重复再补空值,否则补出来的重复记录还要再删一次。

import sqlite3 conn = sqlite3.connect("plant_database.db") cur = conn.cursor() # 1) 按 name 去重,保留 id 最小的那一条 cur.execute(""" DELETE FROM plant_info WHERE id NOT IN ( SELECT MIN(id) FROM plant_info GROUP BY name ) """) # 2) 补全缺席的 category,用“未知”占位 cur.execute("UPDATE plant_info SET category = '未知' WHERE category IS NULL OR category = ''") # 3) 预览乱码记录 cur.execute("SELECT id, name FROM plant_info WHERE name LIKE '%��%' LIMIT 10") for row in cur.fetchall(): print("疑似乱码:", row) conn.commit() conn.close()

去重的逻辑是按 name 分组,每组保留最小编号,其余删除。这个方案在原始数据有几万条时效率不错,但如果你打算保留多个同名的不同品种,就不能用这个办法。补 category 的 UPDATE 语句是把空值统一成“未知”,后面做统计时不会因为空值报错。最后一步用 LIKE '%��%' 查乱码,可以在小规模范围内先确认问题记录数量。如果乱码很普遍,多半是原始文件编码不是 UTF-8,用 iconv 转一次,而不是在数据库里逐条改。

iconv -f GBK -t UTF-8 plant_data.csv > plant_data_utf8.csv

这个命令把 GBK 编码的 CSV 转成 UTF-8。注意前提是原文件确实是 GBK,如果原文件是其他编码,转换后乱码更严重。拿不准时用 file plant_data.csv 先看编码。

4.3 导出训练用的类别清单与划分文件

做完清洗,数据可以用于训练分类或检测模型。很多人拿到植物数据集第一步就想跑 YOLOv5 训练自己的数据集,但你至少要先有类别清单和训练验证划分文件。从数据库导出是效率最高的方式:

import sqlite3 import random conn = sqlite3.connect("plant_database.db") cur = conn.cursor() # 导出所有类别名,写进 classes.txt cur.execute("SELECT DISTINCT name FROM plant_info ORDER BY name") names = [row[0] for row in cur.fetchall()] with open("classes.txt", "w", encoding="utf-8") as f: f.write("\n".join(names)) # 按 8:2 随机划分训练验证集 cur.execute("SELECT id, name, image_path FROM plant_info WHERE image_path IS NOT NULL AND image_path != ''") records = cur.fetchall() random.shuffle(records) split_point = int(len(records) * 0.8) train_set = records[:split_point] val_set = records[split_point:] print(f"训练样本 {len(train_set)},验证样本 {len(val_set)}") print(f"类别数 {len(names)}") conn.close()

DISTINCT 保证类别名称不重复,写出的 classes.txt 顺序固定,这一点对训练特别重要——YOLO 系列训练时类别编号按文本顺序排序,一旦顺序乱,标签和框就对应不上。随机打乱后用 8:2 划分,是最简单的切分方式。如果你手里的数据本身带图片路径,这里导出的就是后续生成标注文件的素材清单。类别名称里不要带空格和括号,训练框架解析起来会出问题,清洗时顺手替换成下划线。

5. 避坑手册:导入失败、编码乱码与字段丢失去哪里查

这份数据我在不同版本上踩过不少坑。按“现象 → 原因 → 解决”的方式整理五条,基本都是拿到文件后最先撞上的问题。

5.1 SQL 导入报错 Unknown collation: 'utf8mb4_0900_ai_ci'

现象:往 MySQL 导入 .sql 文件时报错,提示 unknown collation,导入中断。

原因:文件的建表语句用了 MySQL 8.0 默认字符集排序规则 utf8mb4_0900_ai_ci,而本机是 MySQL 5.7 或 MariaDB,不认识这个规则。

解决:导入前把文件里的 utf8mb4_0900_ai_ci 全部替换成 utf8mb4_general_ci。用编辑器或 sed 批量替换后重新导入。如果是命令行,可以直接执行 sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_general_ci/g' plant_database.sql。这个坑遇到概率极高,因为数据发布者多半是在新版本 MySQL 上导出的。

5.2 Excel 打开 CSV 中文全变乱码

现象:CSV 文件用 Excel 双击打开,中文全部变成“锟斤拷”或“������”。

原因:CSV 是 UTF-8 编码但没有带 BOM,Excel 默认按 GBK 解析,中文就错乱。文件本身没损坏。

解决:用记事本或 VSCode 打开后另存为 UTF-8 with BOM 格式;或者在代码里读文件时用 encoding="utf-8-sig"。如果你用 pandas 读,写成 pd.read_csv("plant_data.csv", encoding="utf-8-sig"),最省事。这个和我在 3.3 写导入代码时用 utf-8-sig 是同一个原因。

5.3 JSON 嵌套字段解析后取不到值

现象:用 Python 读取 JSON 数据库文件,打印顶层键能看到数据,但取某条植物详情时拿到的是 None,或者对象里再嵌套一层取不到别名和用途。

原因:发布者在生成 JSON 时用了不同深度的嵌套结构,有的记录直接在根节点,有的包在 data 或 list 对象里,层级不一致。

解决:先打印一层 JSON 结构再写解析逻辑。常见做法是把根节点数据统一展开:

import json with open("plant_data.json", encoding="utf-8") as f: data = json.load(f) # 兼容两种常见结构:直接是数组,或者包在 data 键下 if isinstance(data, dict) and "data" in data: records = data["data"] else: records = data print(type(records), len(records))

isinstance 判断是为了兼容不同发布版本,先确认 records 是列表再遍历取字段。遇到嵌套不一致,不要写复杂递归,先用这种浅层兼容逻辑把数据拍平。

5.4 image_path 字段有值但前端图片全裂

现象:数据库里 image_path 有路径,比如 /images/ginkgo.jpg,但网页或小程序里图片 404。

原因:路径是发布者本地的绝对路径或相对路径,到你这边没有对应的图片文件。字段有值不代表图片一定存在。

解决:先统计该字段有多少非空记录,再去对应目录确认文件是否真实存在。如果只有路径没有文件,这个字段只能当占位符。做植物识别课程设计时,放弃原图,直接用网络爬图按 name 重新建目录,是更现实的做法。

5.5 SQL 文件太大,命令行导入到一半就断

现象:执行 mysql < plant_database.sql 后报错 “Lost connection to MySQL server during query” 或超时。

原因:默认的 max_allowed_packet 偏小,SQL 里某条 INSERT 语句过大,或者网络连接有中断。批量插数据的 SQL 文件很常见。

解决:导入前在 MySQL 客户端里临时调大限制:

SET GLOBAL max_allowed_packet = 1073741824; SET GLOBAL net_read_timeout = 300; SET GLOBAL net_write_timeout = 300;

然后重新执行导入命令。这是临时生效,重启 MySQL 后恢复默认。遇到超大 SQL 文件,还可以用 mysqldump 的分库分表方式分批次导入,避免一条事务过大。数据库同步工具做迁移时也会遇到类似问题,本质都是单包体积超限。

6. 进阶:给“植物大全”补图片与训练标注

数据本身是结构化字段,想用到识别训练,还需要把 name 转成类别编号,再把图片路径整理成 YOLO 能识别的目录结构。无论你接下来做的是 YOLOv5 训练自己的数据集,还是类似鸟类识别系统的设计与实现这类课程项目,流程都一样:从数据表里导出类别清单,把图片按类别归好目录,再生成 data.yaml。

6.1 从数据表到 data.yaml:训练配置怎么生成

YOLO 系列要找的 data.yaml 核心就三块:训练验证路径、类别数、类别名。类别名必须和 classes.txt 顺序一致,不能手填。我用下面这段脚本从数据库直接生成:

import sqlite3 import yaml conn = sqlite3.connect("plant_database.db") cur = conn.cursor() cur.execute("SELECT DISTINCT name FROM plant_info ORDER BY name") names = [row[0] for row in cur.fetchall()] config = { "path": "./plant_dataset", "train": "images/train", "val": "images/val", "nc": len(names), "names": names } with open("data.yaml", "w", encoding="utf-8") as f: yaml.dump(config, f, allow_unicode=True, default_flow_style=False)

生成后打开确认 nc 和 names 数量对得上。这里最容易被忽略的问题是 names 里有中文,中文类别名在训练框架里解析没问题,但可视化容易乱码。如果你担心这个,可以在导出时做一次拼音或英文映射,保证目录干净。

6.2 先跑通最小样本:类别不乱、标注不偏

拿到数据后别急着全量训练。我第一次做植物识别的时候,直接把整份数据丢进去,训练到一半才发现类别顺序和标签顺序错位,原因是 classes.txt 里出现过重复 name。从那以后,我每次拿到数据集都会强制先走一遍最小流程:挑三五个类别,每个类别找三张图,配好标注,跑一次完整训练和验证,确认类别顺序、标签编号、路径格式全对,再放量跑全量数据。这一步能省掉后面排查标签错乱的大量时间。如果这份数据里 image_path 字段本身就是空的,那就要先解决图片来源问题,否则后面的训练根本无从谈起。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表