SVG文件使用XML格式存储矢量图形信息,路径数据通常存放在path元素的d属性中,包含了移动、绘制、曲线等各类绘图命令。通过Python可以高效地解析这类文件,提取出所需的路径数据用于后续处理。

方法一:使用标准库解析SVG路径
Python内置的xml.etree.ElementTree模块可以解析XML格式的SVG文件,适合提取结构简单、路径命令不复杂的场景。SVG的命名空间需要特别处理,否则无法正确匹配元素。
基础解析示例
以下代码演示了如何读取SVG文件,提取所有path元素的d属性值:
import xml.etree.ElementTree as ET
def extract_svg_paths(svg_file_path):
# 解析SVG文件
tree = ET.parse(svg_file_path)
root = tree.getroot()
# SVG默认命名空间
ns = {'svg': 'http://www.w3.org/2000/svg'}
# 查找所有path元素
path_elements = root.findall('.//svg:path', ns)
path_data_list = []
for path in path_elements:
# 获取d属性值,不存在则返回空字符串
d_attr = path.get('d', '')
if d_attr:
path_data_list.append(d_attr)
return path_data_list
if __name__ == '__main__':
# 替换为你的SVG文件路径
svg_path = 'test.svg'
paths = extract_svg_paths(svg_path)
for idx, p in enumerate(paths, 1):
print(f'第{idx}条路径数据:{p}')
路径数据简单处理
提取到的d属性值是字符串形式的路径命令,比如M 10 20 L 30 40表示移动到(10,20)再画直线到(30,40)。如果需要拆分命令和参数,可以简单处理:
import re
def parse_simple_path(d_str):
# 匹配路径命令和对应的参数,命令为单个字母
pattern = r'([MmZzLlHhVvCcSsQqTtAa])s*([^MmZzLlHhVvCcSsQqTtAa]*)'
matches = re.findall(pattern, d_str)
result = []
for cmd, params in matches:
# 提取参数中的数字
nums = re.findall(r'[-+]?d*.?d+', params)
result.append({
'command': cmd,
'params': [float(num) for num in nums]
})
return result
# 测试解析
d_str = 'M 10 20 L 30 40 C 50 60, 70 80, 90 100'
parsed = parse_simple_path(d_str)
for item in parsed:
print(f'命令:{item["command"]},参数:{item["params"]}')
方法二:使用svgpathtools库解析
svgpathtools是专门处理SVG路径的第三方库,能正确解析各类复杂路径命令,还支持路径的变换、分割、转换等操作,适合专业场景使用。首先需要安装该库:
pip install svgpathtools
提取并解析路径对象
该库可以直接读取SVG文件,将路径转换为可操作的对象,每个路径段都有明确的类型和方法:
from svgpathtools import svg2paths
def extract_paths_with_svgpathtools(svg_file_path):
# 读取SVG文件,返回路径对象列表和属性列表
paths, attributes = svg2paths(svg_file_path)
result = []
for path, attr in zip(paths, attributes):
path_info = {
'd_attr': attr.get('d', ''),
'segments': []
}
# 遍历路径的每个段
for seg in path:
seg_info = {
'type': type(seg).__name__,
'start': (seg.start.real, seg.start.imag),
'end': (seg.end.real, seg.end.imag)
}
# 曲线段额外记录控制点
if hasattr(seg, 'control1'):
seg_info['control1'] = (seg.control1.real, seg.control1.imag)
if hasattr(seg, 'control2'):
seg_info['control2'] = (seg.control2.real, seg.control2.imag)
path_info['segments'].append(seg_info)
result.append(path_info)
return result
if __name__ == '__main__':
svg_path = 'test.svg'
path_objs = extract_paths_with_svgpathtools(svg_path)
for idx, p in enumerate(path_objs, 1):
print(f'第{idx}条路径,段数:{len(p["segments"])}')
for seg in p['segments'][:2]: # 只打印前两个段的信息
print(f' 段类型:{seg["type"]},起点:{seg["start"]},终点:{seg["end"]}')
路径坐标转换示例
svgpathtools还支持将路径坐标转换为其他格式,比如将路径点采样为离散的点坐标:
from svgpathtools import svg2paths, Path
def sample_path_points(svg_file_path, sample_num=100):
paths, _ = svg2paths(svg_file_path)
all_points = []
for path in paths:
points = []
# 对路径进行采样,每个段采样sample_num个点
for seg in path:
for i in range(sample_num):
t = i / sample_num
point = seg.point(t)
points.append((point.real, point.imag))
all_points.append(points)
return all_points
# 测试采样
svg_path = 'test.svg'
sampled = sample_path_points(svg_path, 50)
print(f'共提取{len(sampled)}条路径的采样点')
两种方案对比
不同场景下可以选择不同的解析方案,以下是两种方案的对比:
| 方案 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 标准库xml.etree.ElementTree | 无需安装第三方库,轻量简单 | 只能提取原始字符串,无法解析复杂路径命令和变换 | 简单SVG文件,仅需原始路径字符串的场景 |
| svgpathtools库 | 支持复杂路径解析、坐标变换、路径操作 | 需要安装第三方库,学习成本稍高 | 复杂SVG文件,需要路径结构分析、坐标转换的场景 |
注意事项
- SVG文件可能包含多个命名空间,解析时需要根据实际文件调整命名空间配置。
- 部分SVG的路径数据可能经过transform属性变换,提取时需要结合变换矩阵计算实际坐标,svgpathtools库会自动处理这类变换。
- 如果SVG中包含<use>、<symbol>等复用元素,标准库解析需要额外处理元素引用,svgpathtools库会自动解析这类引用。
PythonSVG路径数据提取svgpathtoolsXML解析修改时间:2026-06-27 23:36:21