Python绘制五代十国时间线:从赵铁头看历史数据可视化

发布时间:2026/9/1 12:42:44
Python绘制五代十国时间线:从赵铁头看历史数据可视化 写这篇五代十国争霸赛第十七篇时我犹豫了半天从哪个人物切入。前面聊了那么多乱世枭雄、沙场宿将今天换个画风讲讲赵铁头的少年时光。赵铁头是谁说白了就是后世民间对少年赵匡胤的一种调侃称呼。铁头意思就是头铁、莽撞、不服输。十几岁的年纪谁还没点中二病赵匡胤也不例外。不过他的中二不是课堂上顶撞老师而是真刀真枪在乱世里闯出来的。这篇文章我想从“少年赵匡胤”这个人物切入顺带把五代十国的政权脉络、时间线整理成一整套可复现的数据分析小项目适合对历史感兴趣、也想练习 Python 数据处理的开发者阅读。1. 背景与核心概念1.1 五代十国到底是个什么样的时代很多读者一听到“五代十国”四个字就头疼不是因为这段历史不精彩而是因为政权名称太多、更替太快记不住。我先用一句话把它说明白唐朝灭亡之后、宋朝建立之前中原地区先后出现了五个短命王朝同时南方和山西等地又存在十几个割据政权这就是五代十国。五代指的是后梁、后唐、后晋、后汉、后周从 907 年朱温篡唐建立后梁开始到 960 年赵匡胤建立宋朝结束一共五十多年。这五个政权基本都在中原地区一个接一个更替最长的后梁也只有十六年最短的后汉甚至只有四年。十国则包括前蜀、后蜀、吴、南唐、吴越、楚、闽、南汉、南平、北汉等政权分布在南北方不同区域存在时间参差不齐有些甚至比五代还长。这个时代的特点非常鲜明军阀混战、武将掌权、皇位更迭频繁。但也正是这种乱世催生了一批从底层崛起的人物赵匡胤就是其中最典型的代表。1.2 “赵铁头”这个外号是怎么来的“赵铁头”不是史书上的正式称号。在民间故事和网络讲述里大家喜欢用“铁头”形容少年赵匡胤的性格认准的事情不回头打架不怕事遇到不公平的事一定要管。这类少年意气放到今天就是典型的“中二”气质。赵匡胤出身武将家庭父亲赵弘殷是后唐、后汉时期的将领。按理说他算是官宦子弟但那个年代武将家庭的日子并不稳定家族随军迁徙、战乱离散都是常态。少年赵匡胤不爱死读书更喜欢骑射、武艺和结交朋友。有记载说他在年轻时候曾经离家出走、四处闯荡在乱世里寻找自己的出路。这种经历放在那个时代并不稀奇很多后来称王称霸的人物都有类似的游历过程只不过赵匡胤把这段少年时光走成了日后开创宋朝的起点。理解“赵铁头”这个人其实也是在理解五代十国底层青年的生存状态。那是一个没有安全感的时代普通人的命运随时会被战争改写敢闯敢拼的人才有机会活下来、站出来。1.3 为什么把历史梳理写成 Python 项目我写历史类内容的时候经常遇到一个问题脑子里的时间线容易乱。五代十国这些政权今天这个灭了明天那个建要是光靠死记硬背效率很低。后来我习惯把历史事件整理成结构化数据再用代码做可视化这样一条时间线画出来整个时代的轮廓就清楚多了。从这个出发点来看本篇文章除了聊赵铁头的少年时光还会带着大家用 Python 把五代十国的主要政权数据整理成表格、绘制成时间线图。历史部分负责提供背景代码部分负责把背景变成可以交互、可以复用的分析工具。哪怕你是第一次接触 pandas 和 matplotlib跟着步骤走也能跑出结果。2. 环境准备与版本说明2.1 开发环境选择本文示例在 Python 3.9 以上环境验证。如果你用的是 Anaconda 或者系统自带的 Python 3.8 也能运行但建议尽量使用 3.9 以上版本避免个别语法和依赖库的兼容问题。操作系统方面Windows、macOS、Linux 都可以。文章中的代码不涉及系统级命令唯一需要注意的是中文字体配置Windows 和 macOS 稍有差异我会在常见问题部分专门说明。2.2 安装需要用到的库核心依赖只有两个pandas 和 matplotlib。pandas 负责数据清洗和表格处理matplotlib 负责绘图。如果你还没有安装可以在终端执行pip install pandas matplotlib版本方面不用刻意追求最新版pandas 1.5 以上、matplotlib 3.7 以上的常见版本都能兼容本文代码。如果不确定当前环境版本可以执行pip list | grep pandas pip list | grep matplotlib2.3 项目目录结构为了方便管理我们先创建一个项目文件夹wudai_shiguo/ ├── data/ │ └── regimes.json ├── timeline.py └── requirements.txtdata/regimes.json存放五代十国的政权数据。timeline.py是主程序负责读取数据、生成时间线图表。requirements.txt记录依赖库方便其他人复现环境。3. 五代十国政权脉络梳理3.1 五代顺序与更替五代的时间线并不复杂难记的是开国皇帝和政权特点。先看一张表政权起止年份开国君主都城主要特点后梁907-923朱温开封唐朝的终结者内部矛盾尖锐后唐923-936李存勖洛阳沙陀人建立一度号称“中兴”后晋936-947石敬瑭开封割让幽云十六州争议很大后汉947-951刘知远开封存在时间最短四年后周951-960郭威开封柴荣改革为宋朝奠定基础这五个政权之间并不是简单的父子传承而是通过军事政变、战争吞并完成的更替。后唐灭后梁后晋靠契丹帮助灭后唐后汉又取代后晋后周则取代后汉。中间的每一次更替都伴随着大规模战争和权力清洗。3.2 十国有哪些十国的情况比较复杂因为有些政权存在时间跨度超过五代的整体时间而且位置分散。我把主要政权整理成下面的表格政权起止年份开国君主大致区域吴902-937杨行密江苏、安徽一带南唐937-975李昪苏皖赣等地吴越907-978钱镠浙江一带楚907-951马殷湖南一带闽909-945王审知福建一带南汉917-971刘龑广东、广西一带前蜀907-925王建四川一带后蜀934-965孟知祥四川一带南平924-963高季兴湖北江陵一带北汉951-979刘崇山西北部单看这张表可能还是觉得杂乱等到第四节我们用代码把起止年份做成时间线视觉效果会直观很多。3.3 赵匡胤在时间线上的位置赵匡胤出身于后唐到后汉这个时间段他成年之后正好赶上后周建立。后周世宗柴荣在位时赵匡胤凭借战功步步高升最终在后周显德七年也就是 960 年发动陈桥兵变建立北宋。从时间线看赵匡胤的少年时期正好横跨后汉、后周两个政权。他在乱世中成长亲眼见证了一个一个政权像走马灯一样兴起又覆灭。这种经历让他比谁都清楚武将专权的危害所以后来他通过“杯酒释兵权”等一系列手段把兵权牢牢掌握在自己手里。赵铁头少年时的“中二”等到中年就变成了政治智慧。4. 完整实战用 Python 绘制五代十国政权时间线这一节是文章的重点。我们不做枯燥的背诵直接把数据交给代码用一张时间线图把五代十国的政权存续关系展示出来。4.1 创建项目结构先创建目录mkdir wudai_shiguo cd wudai_shiguo mkdir data然后在项目根目录下创建requirements.txtpandas1.5 matplotlib3.74.2 准备政权数据文件新建data/regimes.json把五代的五个政权和十国的主要政权整理成 JSON 数据。这里需要注意一点JSON 文件不支持注释所以我把说明信息放到字段里。{ five_dynasties: [ {name: 后梁, start: 907, end: 923, founder: 朱温, capital: 开封}, {name: 后唐, start: 923, end: 936, founder: 李存勖, capital: 洛阳}, {name: 后晋, start: 936, end: 947, founder: 石敬瑭, capital: 开封}, {name: 后汉, start: 947, end: 951, founder: 刘知远, capital: 开封}, {name: 后周, start: 951, end: 960, founder: 郭威, capital: 开封} ], ten_kingdoms: [ {name: 前蜀, start: 907, end: 925, founder: 王建, area: 四川一带}, {name: 后蜀, start: 934, end: 965, founder: 孟知祥, area: 四川一带}, {name: 吴, start: 902, end: 937, founder: 杨行密, area: 江苏安徽一带}, {name: 南唐, start: 937, end: 975, founder: 李昪, area: 苏皖赣等地}, {name: 吴越, start: 907, end: 978, founder: 钱镠, area: 浙江一带}, {name: 楚, start: 907, end: 951, founder: 马殷, area: 湖南一带}, {name: 闽, start: 909, end: 945, founder: 王审知, area: 福建一带}, {name: 南汉, start: 917, end: 971, founder: 刘龑, area: 广东广西一带}, {name: 南平, start: 924, end: 963, founder: 高季兴, area: 湖北江陵一带}, {name: 北汉, start: 951, end: 979, founder: 刘崇, area: 山西北部} ] }注意年份直接写成数字不要加引号否则后面转换类型会多一点步骤。4.3 编写主程序创建timeline.py实现读取 JSON、转 DataFrame、绘制时间线三个功能。# 文件路径timeline.py import json import pandas as pd import matplotlib.pyplot as plt # 设置中文字体避免图表出现方框 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC, WenQuanYi Zen Hei] plt.rcParams[axes.unicode_minus] False def load_data(path): 读取 JSON返回五代的 DataFrame 和十国的 DataFrame with open(path, r, encodingutf-8) as f: data json.load(f) five pd.DataFrame(data[five_dynasties]) ten pd.DataFrame(data[ten_kingdoms]) return five, ten def plot_timeline(ax, df, color): 在指定子图上绘制横向条形时间线 for _, row in df.iterrows(): start int(row[start]) end int(row[end]) ax.barh(row[name], end - start, leftstart, colorcolor, edgecolorwhite, height0.6) def main(): # 1. 加载数据 five, ten load_data(data/regimes.json) # 2. 计算存续时长 five[duration] five[end] - five[start] ten[duration] ten[end] - ten[start] print(五代存续时长) print(five[[name, start, end, duration]]) print(\n十国存续时长) print(ten[[name, start, end, duration]]) # 3. 绘制时间线 fig, (ax1, ax2) plt.subplots(2, 1, figsize(12, 10)) plot_timeline(ax1, five, #C0392B) plot_timeline(ax2, ten, #2980B9) ax1.set_title(五代政权更迭时间线907-960, fontsize14) ax2.set_title(十国政权存在时间线约902-979, fontsize14) ax1.set_xlim(880, 990) ax2.set_xlim(880, 990) ax1.set_xlabel(年份) ax2.set_xlabel(年份) ax1.grid(axisx, linestyle--, alpha0.6) ax2.grid(axisx, linestyle--, alpha0.6) plt.tight_layout() plt.savefig(timeline.png, dpi150) plt.show() if __name__ __main__: main()这段代码本身不复杂核心逻辑有三个load_data负责读 JSON 并转成 pandas 的 DataFrame。转换之后每个政权就变成表格里的一行字段包括名称、开始年份、结束年份等。plot_timeline是绘图函数它对 DataFrame 的每一行调用一次barh。barh是横向条形图left参数确定条形图的起点end - start是条形的长度正好对应政权存续时间。main里先打印存续时长再创建两个子图分别绘制五代和十国最后保存为timeline.png并在屏幕上显示。4.4 运行与验证在项目根目录执行python timeline.py正常情况会先输出如下内容五代存续时长 name start end duration 0 后梁 907 923 16 1 后唐 923 936 13 2 后晋 936 947 11 3 后汉 947 951 4 4 后周 951 960 9 十国存续时长 name start end duration 0 前蜀 907 925 18 1 后蜀 934 965 31 2 吴 902 937 35 3 南唐 937 975 38 4 吴越 907 978 71 5 楚 907 951 44 6 闽 909 945 36 7 南汉 917 971 54 8 南平 924 963 39 9 北汉 951 979 28从这组数据就能直观感受到五代和十国的差异五代政权普遍短命最短的后汉只有 4 年十国政权反而稳定得多吴越存在了 71 年南汉 54 年楚 44 年。这就是为什么“五代”更替频繁而“十国”中的某些政权反而能偏安一方。图表生成之后你会看到上下两张横条图上半部分用红色表示五代五个条形横向排列长度都很短说明政权更替很快。下半部分用蓝色表示十国条形明显更长说明割据政权相比中原王朝更稳定。如果你只想保存图片、不弹窗显示可以把最后一行plt.show()注释掉只保留plt.savefig(timeline.png, dpi150)。4.5 如何把赵铁头放进时间线有人可能会问这张图里没有赵匡胤怎么体现“赵铁头少年时光”我们可以加一个简单的标记。在timeline.py里新增一个函数专门用来把重要人物标注到时间线上def plot_person(ax, year, name, color#000000): 在指定年份上方标注人物名称 ax.axvline(xyear, colorcolor, linestyle--, linewidth1, alpha0.7) ax.text(year 0.5, -0.3, name, fontsize10, colorcolor)然后在main()里调用plot_person(ax1, 927, 赵匡胤出生) plot_person(ax1, 960, 陈桥兵变)这样一来时间线上就能清楚看到赵匡胤出生在后唐时期他的少年时光横跨后晋、后汉而到了后周他开始登上历史舞台。一张图把人物和时代串起来比单纯背年份要直观得多。5. 常见问题与排查思路写代码跑数据的时候多少会遇到一些问题。我把这类历史数据可视化项目最常见的报错和排查思路整理成表格方便你对照处理。问题现象常见原因解决思路读 JSON 时报错 JSONDecodeError文件编码不是 UTF-8或者 JSON 格式有多余逗号、注释用 UTF-8 保存 JSON删除注释和多余逗号中文显示为方框系统缺少对应中文字体或 matplotlib 未设置字体在代码开头设置plt.rcParams[font.sans-serif]换成系统中已安装的字体end - start报类型错误start 或 end 被识别成字符串确保 JSON 中年份是数字或者在 DataFrame 里用pd.to_numeric转成数值图表太拥挤条形重叠看不清政权数量多、画布太小调大figsize增大ylim范围或者把五代和十国分成两个子图坐标轴显示负号异常数据中可能出现负数或未设置 Unicode 负号添加plt.rcParams[axes.unicode_minus] False保存图片时提示权限不足当前目录不可写修改输出路径到当前用户的临时目录或桌面如果你在运行代码时遇到其他问题建议先通过print(df.dtypes)查看数据类型再确认数据文件格式。90% 的异常都可以从“数据格式不正确”这个方向找到答案。6. 最佳实践与工程建议6.1 历史数据不要硬编码在 Python 文件里我最早写整理程序的时候习惯直接在 Python 文件里写一堆字典five_data [ {name: 后梁, start: 907}, ... ]这种写法对一次性脚本没问题但如果数据量变大或者想给其他人复用就很麻烦。更好的做法是把数据放到 JSON、CSV 或数据库里代码只负责读取和处理。数据与逻辑分离方便修改、维护和扩展。如果你想进一步做历史知识管理可以考虑把数据导入 SQLite比如CREATE TABLE regimes ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, start_year INTEGER NOT NULL, end_year INTEGER NOT NULL, category TEXT NOT NULL );然后通过 SQL 按年份范围查询能做的事情就更多了。6.2 可视化注意配色与可读性画历史时间线的时候配色尽量不要超过两种主色否则图会显得很乱。我用红色代表五代蓝色代表十国两个子图分开绘制视觉上区分明显。另外横轴的年份范围要设置合理。五代十国整体跨度大约从 902 年到 979 年所以set_xlim(880, 990)既能留出缓冲又能把主要信息完整展示。如果你画的是全国统一政权可以按实际年份调整范围避免出现大段空白。6.3 从时间线延伸到知识图谱时间线只是历史可视化的第一步。后续你还可以把“政权—开国君主—末代君主—都城—重要事件”做成关系图谱。用 NetworkX 绘制政权攻伐关系图把“谁灭了谁”的关系拉成一张网。使用 Pyecharts 生成可交互的时间线鼠标悬停就能看到详细信息。给每个政权补充存续时长、疆域范围估算做更深入的数据分析。这些方向都很有意思核心还是先把基础数据整理干净后面的扩展才有价值。7. 总结与学习路线这一篇从赵铁头的少年时光聊到了五代十国的整体时间线再用 Python 把这段历史做成可视化图表算是一次跨界的整理。通过实际操作你应该掌握了几个关键点五代十国的主要政权顺序和存续时间Pandas 如何读取 JSON 数据并做简单计算Matplotlib 如何绘制横向时间线图以及遇到中文字体、数据类型、图表布局问题时怎么排查。下一步有两个学习方向。一个方向是继续深入历史把赵匡胤从赵铁头变成宋太祖的过程完整梳理一遍研究陈桥兵变、杯酒释兵权背后的政治逻辑。另一个方向是继续提升数据处理能力把本文的脚本改造成更完整的“历史知识管理系统”比如加上政权兴衰原因标签、战争事件记录再用 Flask 或 FastAPI 做成一个在线查询页面。我在整理五代十国数据的时候最直观的感受是数据一旦结构化历史就不再是零散的人名和年份而是一张可以缩放、可以检索的网。赵铁头的少年时光虽然短暂但放到整条时间线上看恰好是一个旧时代结束、新时代开启的转折点。如果你手头也有感兴趣的历史素材不妨用这种方法做成属于你自己的时间线那种“把乱世看明白”的感觉和单纯看文章完全不同。