摘要
在数据分析与报表自动化场景中,excel 图表往往承载着关键业务信息,但常规库对图表结构与样式的解析能力有限。本文基于 openxml 规范,通过将 .xlsx 文件视为 zip 压缩包,直接解析 xl/charts/chart*.xml,实现了对 excel 图表元数据的精准提取。使用 python 的 urllib、zipfile 与 xml.etree.elementtree,完整获取了图表标题、系列名称、x/y 轴数据,以及标题、坐标轴和数据系列的字体与字号信息。实践结果表明,该方法无需依赖 excel 环境,适用于线上 excel 文件解析、图表规范校验及报表自动化处理,为 excel 图表的深度解析与二次利用提供了一种高效可行的技术方案。
一、背景介绍
在实际项目中,我们经常会遇到这样的需求:
线上 excel 文件(http 地址)
不关心单元格数据,而是需要:
- 图表标题
- 系列名称
- x / y 轴数据
- 图表、坐标轴、系列的字体和字号
然而,openpyxl 等库并不能完整解析 excel 图表的样式和结构。
事实上,.xlsx 本质上是一个 zip 压缩包,图表信息存储在:
xl/charts/chart*.xml
只要我们直接解析这个 xml,就能拿到几乎全部图表元数据。
二、整体思路
技术路线
1.通过 urllib 下载 excel 文件
2.使用 zipfile 读取 xlsx 内部结构
3.定位 xl/charts/chart1.xml
4.使用 xml.etree.elementtree 解析图表 xml
5.按 openxml 规范解析:
- 标题(title)
- 系列(ser)
- 分类轴(catax)
- 数值轴(valax)
- 字体、字号
- x / y 轴数据
三、核心代码实现
完整函数代码
import xml.etree.elementtree as et
from zipfile import zipfile
import io
import urllib.request
def get_chat_info(direct_link):
result = {}
res = {}
try:
# 下载 excel 文件
file = urllib.request.urlopen(direct_link).read()
archive = zipfile(io.bytesio(file))
try:
# 读取图表 xml
data = archive.read('xl/charts/chart1.xml')
res['code'] = 200
res['msg'] = "获取图表信息成功"
tree = et.parse(io.bytesio(data))
root = tree.getroot()
# 命名空间
ns = {
'c': 'http://schemas.openxmlformats.org/drawingml/2006/chart',
'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'
}
# ================== 图表标题 ==================
title_element = root.find('.//c:title/c:tx/c:rich', ns)
if title_element is not none:
title_text = ""
for t in title_element.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}t'):
title_text += t.text
result['title'] = title_text
title_ax_element = root.find('.//c:chart/c:title/c:tx', ns)
if title_ax_element is not none:
tx_pr = title_ax_element.find('.//a:defrpr', ns)
if tx_pr is not none:
latin = tx_pr.find('.//a:latin', ns)
result['title_font'] = latin.get('typeface') if latin is not none else "no"
result['title_size'] = tx_pr.get('sz') or "no"
# ================== 系列名称 ==================
ser_elements = root.findall('.//c:chart/c:plotarea/*/c:ser', ns)
series_name = ""
for ser in ser_elements:
v = ser.find('.//c:v', ns)
if v is not none:
series_name = v.text
result['series_name'] = series_name
# ================== x / y 数据 ==================
x_values, y_values = [], []
for num_ref in root.findall('.//c:numref', ns):
for v in num_ref.findall('.//c:v', ns):
y_values.append(v.text)
for pt in root.findall('.//c:cat/c:strref/c:strcache/c:pt', ns):
v = pt.find('.//c:v', ns)
if v is not none:
x_values.append(v.text)
result['x_values'] = x_values
result['y_values'] = y_values
# ================== 数值轴 ==================
val_ax = root.find('.//c:valax', ns)
if val_ax is not none:
tx_pr = val_ax.find('.//c:txpr/a:p/a:ppr/a:defrpr', ns)
if tx_pr is not none:
latin = tx_pr.find('.//a:latin', ns)
result['valax_font'] = latin.get('typeface') if latin is not none else "no"
result['valax_size'] = tx_pr.get('sz') or "no"
# ================== 分类轴 ==================
cat_ax = root.find('.//c:catax', ns)
if cat_ax is not none:
tx_pr = cat_ax.find('.//c:txpr/a:p/a:ppr/a:defrpr', ns)
if tx_pr is not none:
latin = tx_pr.find('.//a:latin', ns)
result['catax_font'] = latin.get('typeface') if latin is not none else "no"
result['catax_size'] = tx_pr.get('sz') or "no"
# ================== 系列字体 ==================
ser = root.find('.//c:chart/c:plotarea/*/c:ser', ns)
if ser is not none:
tx_pr = ser.find('.//a:defrpr', ns)
if tx_pr is not none:
latin = tx_pr.find('.//a:latin', ns)
result['ser_font'] = latin.get('typeface') if latin is not none else "no"
result['ser_size'] = tx_pr.get('sz') or "no"
res['data'] = result
except:
res['code'] = 404
res['msg'] = "未找到图表信息"
except:
res['code'] = 500
res['msg'] = "未获取excel信息"
return res
测试示例
aa = get_chat_info("http://192.168.31.161:8080/555.xlsx")
print(aa)
四、运行结果示例
{
"code": 200,
"msg": "获取图表信息成功",
"data": {
"title": "各季度采购合理性折线图",
"title_font": "宋体",
"title_size": "1200",
"series_name": "采购合理性",
"x_values": [
"2018-1", "2018-2", "2018-3", "2018-4",
"jan-19", "2019-2", "2019-3", "2019-4",
"2020-1", "2020-2", "2020-3", "2020-4",
"2021-1", "2021-2", "2021-3", "2021-4",
"2022-1", "2022-2", "2022-3", "2022-4"
],
"y_values": [
"0.99", "0.92", "0.91", "0.37", "0.85",
"0.97", "0.8", "0.88", "0.67", "0.91",
"0.76", "0.75", "0.99", "0.95", "0.89",
"0.83", "0.44", "0.75", "0.94", "0.41"
],
"valax_font": "宋体",
"valax_size": "1000",
"catax_font": "宋体",
"catax_size": "1000",
"ser_font": "宋体",
"ser_size": "1000"
}
}
五、关键知识点总结
.xlsx 是 zip 文件
图表数据在 xl/charts/chart*.xml
excel 图表完全遵循 openxml 规范
字体大小单位为 1/100 磅(pt)
- 1000 = 10pt
- 1200 = 12pt
六、适用场景
- 自动化审计 excel 报表
- 图表规范校验(字体 / 标题 / 数据完整性)
- excel → 图表数据 → web 可视化
- 报表 ai / llm 解析前的数据结构化
延伸:python使用openpyxl从url读取excel并获取单元格样式
到此这篇关于python解析excel图表chart的信息实战指南的文章就介绍到这了,更多相关python解析excel图表内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论