引言
PowerPoint(PPT)文件的自动化处理是办公自动化和数据提取的常见需求。本文将介绍如何通过Python的python-pptx
库,将PPT文件的样式、结构、文本内容等信息解析为标准化的JSON格式,为后续的自动化处理、数据迁移或样式复用提供基础。
核心代码解析
1. 颜色转换函数:rgb_to_hex
将RGB颜色值(如(255, 0, 0)
)转换为十六进制字符串(如#FF0000
)。
当前代码存在缺陷:原函数直接返回RGB元组,而非十六进制字符串。以下是修正后的实现:
python
def rgb_to_hex(rgb):
"""将 RGB 颜色转换为十六进制字符串(如 #FF0000)"""
if rgb is None:
return None
return f"#{rgb[0]:02X}{rgb[1]:02X}{rgb[2]:02X}"
2. 解析单个形状:parse_shape
提取形状的类型、位置、样式、文本内容等信息,支持文本框、表格、图片等类型。
关键步骤:
- 基础属性 :形状类型(如
MSO_SHAPE_TYPE.TEXT_BOX
)、位置(left
,top
)、尺寸(width
,height
)。 - 填充样式:颜色类型(纯色/渐变)、颜色值(十六进制)。
- 边框样式 :颜色、线宽、虚线类型(如
MSO_LINE_DASH_STYLE.DASH
)。 - 文本样式:段落对齐、字体名称、大小、加粗/斜体、颜色。
- 特殊处理 :
- 表格:解析行、列及单元格内容。
- 图片:记录尺寸信息。
示例输出(文本框):
json
{
"type": 1, // MSO_SHAPE_TYPE.TEXT_BOX
"name": "Text Box 1",
"text": "Hello World",
"fill": {
"type": "MSO_FILL.SOLID",
"color": "#FF0000"
},
"line": {
"color": "#000000",
"width": 12700, // EMU单位
"dash_style": "MSO_LINE_DASH_STYLE.SOLID"
},
"text_style": {
"paragraphs": [
{
"text": "Hello World",
"runs": [
{
"text": "Hello World",
"font": {
"name": "Arial",
"size": 24,
"bold": false,
"color": "#000000"
}
}
]
}
]
}
}
3. 解析整个PPT:parse_presentation
遍历PPT的每一页和每个形状,调用parse_shape
生成结构化数据。
示例输出(JSON片段):
json
{
"slides": [
{
"slide_number": 254, // PPT内部ID
"shapes": [
{
"type_name": "MSO_SHAPE_TYPE.TABLE",
"table": [
[
{"text": "Header 1", "row_span": 1, "col_span": 1},
{"text": "Header 2", "row_span": 1, "col_span": 1}
],
[
{"text": "Row 1", "row_span": 1, "col_span": 1},
{"text": "Data", "row_span": 1, "col_span": 1}
]
]
}
]
}
]
}
4. 保存为JSON:save_to_json
将解析结果以可读格式保存为文件。
python
def save_to_json(data, output_path):
with open(output_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
使用示例
1. 安装依赖
bash
pip install python-pptx
2. 运行代码
python
if __name__ == "__main__":
input_pptx = "template.pptx" # 输入PPT路径
output_json = "presentation_info.json" # 输出JSON路径
parsed_data = parse_presentation(input_pptx)
save_to_json(parsed_data, output_json)
3. 输出JSON结构
json
{
"slides": [
{
"slide_number": 254,
"shapes": [
{
"type": 1,
"name": "Text Box 1",
"text": "Sample Text",
"fill": {"type": "MSO_FILL.BACKGROUND", "color": null},
"line": {"color": null, "width": 0, "dash_style": null},
"text_style": {
"paragraphs": [
{
"text": "Sample Text",
"runs": [
{
"text": "Sample Text",
"font": {
"name": "Calibri",
"size": 11,
"bold": false,
"color": "#000000"
}
}
]
}
]
}
}
]
}
]
}
核心功能与适用场景
1. 支持的形状类型
类型名称 | 对应值 | 描述 |
---|---|---|
MSO_SHAPE_TYPE.TEXT_BOX |
1 | 文本框 |
MSO_SHAPE_TYPE.TABLE |
19 | 表格 |
MSO_SHAPE_TYPE.PICTURE |
17 | 图片 |
其他形状 | 根据MSO枚举 | 形状、线条等 |
2. 典型应用场景
- 样式复用:提取模板样式,批量生成符合规范的PPT。
- 数据迁移:将PPT内容导出为JSON,用于数据分析或内容管理。
- 自动化生成 :结合JSON数据,动态生成PPT(需反向实现
apply
功能)。
注意事项
-
单位转换:
- PPT中的尺寸单位为EMU (English Metric Unit),可通过
shape.width/9525
转换为像素(1 EMU ≈ 0.01像素)。
- PPT中的尺寸单位为EMU (English Metric Unit),可通过
-
异常处理:
- 部分形状可能无文本框(如图片),需通过
shape.has_text_frame
判断。 - 颜色值可能为
None
(如填充为透明色),需设置默认值。
- 部分形状可能无文本框(如图片),需通过
-
扩展建议:
- 支持更多样式:如阴影、3D效果。
- 反向生成PPT:根据JSON数据重建PPT文件。
总结
通过本文的代码和解析,开发者可以快速实现PPT文件的自动化解析与数据提取。无论是学术研究、企业报告自动化,还是结合LLM生成内容,这一工具链都能提供强大的基础支持。下一步,你可以尝试:
- 结合LLM生成内容 :用GPT生成文本后,填充到JSON的
text
字段。 - 可视化样式:将JSON数据渲染为网页或图表,用于PPT设计预览。
通过Python和JSON的结合,PPT的自动化处理从未如此简单!
python
import json
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.enum.text import PP_ALIGN
from pptx.enum.dml import MSO_FILL, MSO_LINE_DASH_STYLE
def rgb_to_hex(rgb):
"""将 RGB 颜色转换为十六进制字符串(如 #FF0000)"""
if rgb is None:
return None
return (rgb[0], rgb[1], rgb[2])
def parse_shape(shape):
"""解析单个 Shape 的信息"""
data = {
"type": shape.shape_type,
"type_name": str(MSO_SHAPE_TYPE(shape.shape_type)),
"name": shape.name,
"left": shape.left,
"top": shape.top,
"width": shape.width,
"height": shape.height,
"rotation": shape.rotation,
"text": "",
"fill": {},
"line": {},
"text_style": {}
}
# 解析填充样式
fill = shape.fill
try:
data["fill"] = {
"type": str(MSO_FILL(fill.type)),
"color": rgb_to_hex(fill.fore_color.rgb) if fill.fore_color else None
}
except:
data["fill"] = {
"type": str(MSO_FILL(fill.type)),
"color": None
}
# 解析边框样式
line = shape.line
# try:
data["line"] = {
"color": rgb_to_hex(line.color.rgb) if line.color.type else None,
"width": line.width,
"dash_style": str(MSO_LINE_DASH_STYLE(line.dash_style)) if line.dash_style else None
}
# except:
# print()
# 解析文本样式(如果存在文本框)
if shape.has_text_frame:
text_frame = shape.text_frame
paragraphs = []
for paragraph in text_frame.paragraphs:
runs = []
for run in paragraph.runs:
run_data = {
"text": run.text,
"font": {
"name": run.font.name,
"size": run.font.size.pt,
"bold": run.font.bold,
"italic": run.font.italic,
"color": rgb_to_hex(run.font.color.rgb)
}
}
runs.append(run_data)
paragraph_data = {
"text": paragraph.text,
"runs": runs,
"level": paragraph.level,
"alignment": str(PP_ALIGN(paragraph.alignment)) if paragraph.alignment else None
}
paragraphs.append(paragraph_data)
data["text_style"] = {
"paragraphs": paragraphs
}
data["text"] = text_frame.text
# 处理表格
if shape.shape_type == MSO_SHAPE_TYPE.TABLE:
table = shape.table
rows = []
for row in table.rows:
cells = []
for cell in row.cells:
cell_data = {
"text": cell.text.strip(),
"row_span": cell.row_span,
"col_span": cell.col_span
}
cells.append(cell_data)
rows.append(cells)
data["table"] = rows
# 处理图片
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
data["image"] = {
"width": shape.width,
"height": shape.height
}
return data
def parse_presentation(pptx_path):
"""解析整个 PPT 文件并返回 JSON 结构"""
prs = Presentation(pptx_path)
presentation_data = {
"slides": []
}
for slide_idx, slide in enumerate(prs.slides):
slide_data = {
"slide_number": slide.slide_id,
"shapes": []
}
for shape in slide.shapes:
shape_data = parse_shape(shape)
slide_data["shapes"].append(shape_data)
presentation_data["slides"].append(slide_data)
return presentation_data
def save_to_json(data, output_path):
"""将解析后的数据保存为 JSON 文件"""
with open(output_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
# 使用示例
if __name__ == "__main__":
input_pptx = "template.pptx" # 输入的 PPT 文件路径
output_json = "presentation_info.json" # 输出的 JSON 文件路径
# 解析 PPT
parsed_data = parse_presentation(input_pptx)
# 保存为 JSON
save_to_json(parsed_data, output_json)