python利用lxml库剩下操作svg图片
作者:梦想橡皮擦
在大多数场景中,我们都用 lxml 库解析网页源码,但你是否知道,lxml 库也是可以操作 svg 图片的。我们可以使用 lxml 中的 etree 模块来解析 SVG 文件,然后使用 SVG 中的各种元素和属性来进行操作。
lxml 操作 svg 图片示例
在本篇博客的入门篇,我们首先使用一下 lxml 库解析 svg 文件,并修改它的颜色。
SVG 图片生成,可以查看 《Python 生成 svg 图片,一篇博客带你掌握 Python 与 svg 之间的操作》 这篇博客。
借用 svgwrite 库,生成一个红色背景的 svg 图片。
import svgwrite dwg = svgwrite.Drawing('demo.svg', size=(100, 20), profile='tiny') dwg.add(dwg.rect(insert=(0, 0), size=(100, 20), fill='red')) phone_number = '橡皮擦' dwg.add(dwg.text(phone_number, insert=(0, 15), fill='white', font_size=12)) dwg.save()
同时查看一下 svg 内容,如下所示。
<?xml version="1.0" encoding="utf-8" ?> <svg baseProfile="tiny" height="20" version="1.2" width="100" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs/> <rect fill="red" height="20" width="100" x="0" y="0"/> <text fill="white" font-size="12" x="0" y="15">橡皮擦</text> </svg>
我们需要替换的内容是 fill="white" ,将其修改为 fill="#03a9f4"。使用 lxml 读取该文件,进行颜色替换。
from lxml import etree # 解析SVG文件 svg_file = 'demo.svg' with open(svg_file, 'rb') as f: svg_data = f.read() parser = etree.XMLParser(remove_blank_text=True) svg_tree = etree.fromstring(svg_data, parser) # 修改颜色 for element in svg_tree.iter(): if 'fill' in element.attrib: # 替换颜色 element.attrib['fill'] = element.attrib['fill'].replace('white', '#03a9f4') # 保存修改后的SVG文件 with open('modified_demo.svg', 'wb') as f: f.write(etree.tostring(svg_tree, pretty_print=True))
此时替换之后,再次查看 svg 图片源码内容,如下所示。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="tiny" height="20" version="1.2" width="100"> <defs/> <rect fill="red" height="20" width="100" x="0" y="0"/> <text fill="#03a9f4" font-size="12" x="0" y="15">橡皮擦</text> </svg>
重点注意 text 元素部分,发现 fill 属性的值已经被修改成最新的颜色了。
lxml 给 svg 图片添加新元素
使用 append() 函数可以给 svg 图片添加新元素,例如下述代码将添加一个矩形到图片中。
from lxml import etree # 解析SVG文件 svg_file = 'demo.svg' with open(svg_file, 'rb') as f: svg_data = f.read() parser = etree.XMLParser(remove_blank_text=True) svg_tree = etree.fromstring(svg_data, parser) new_element = etree.Element('rect', x='5', y='5', width='50', height='20', style='fill:#03a9f4') svg_tree.append(new_element) # 保存修改后的SVG文件 with open('modified_demo.svg', 'wb') as f: f.write(etree.tostring(svg_tree, pretty_print=True))
这里矩形的定位并没有精确计算,实现的效果图如下所示。
lxml 删除 svg 图片中的元素
除新增外,还可以对 svg 中元素进行删除操作。示例代码如下所示。
from lxml import etree # 解析SVG文件 svg_file = 'modified_demo.svg' with open(svg_file, 'r') as f: svg_data = f.read() parser = etree.XMLParser(remove_blank_text=True) svg_tree = etree.fromstring(svg_data, parser) # 通过 xpath 查找需要删除的元素 elements_to_remove = svg_tree.xpath("//text") print(elements_to_remove) for element in elements_to_remove: element.getparent().remove(element)
运行代码会发现通过 xpath 无法查找到目标元素 text,这时因为 SVG 文件中含有命名空间,导致 xpath 语法查询不到相应的元素,可以通过为 xpath 语法指定命名空间来解决这个问题。
添加命名空间之后的提取语法如下所示。
from lxml import etree # 解析SVG文件 svg_file = 'modified_demo.svg' svg_tree = etree.parse(svg_file) root = svg_tree.getroot() # 获取命名空间 ns = {'svg': root.nsmap[None]} # 通过 xpath 查找需要删除的元素 elements_to_remove = svg_tree.xpath("//svg:text", namespaces=ns) print(elements_to_remove)
尤其注意 xpath 部分需要使用 //svg:text 进行提取。
如果不提前生命 ns 变量,可以使用下述代码进行指定命名空间。
elements_to_remove = svg_tree.xpath("//svg:circle", namespaces={'svg': 'http://www.w3.org/2000/svg'})
有了上述基础之后,完整的 lxml 删除元素代码如下所示。
from lxml import etree # 解析SVG文件 svg_file = 'modified_demo.svg' svg_tree = etree.parse(svg_file) root = svg_tree.getroot() # 获取命名空间 ns = {'svg': root.nsmap[None]} # 通过 xpath 查找需要删除的元素 elements_to_remove = svg_tree.xpath("//svg:text", namespaces=ns) print(elements_to_remove) for element in elements_to_remove: element.getparent().remove(element) # 保存修改后的 SVG 文件 with open('modified_demo1.svg', 'wb') as f: f.write(etree.tostring(svg_tree, pretty_print=True))
以上就是python利用lxml库剩下操作svg图片的详细内容,更多关于python lxml操作svg的资料请关注脚本之家其它相关文章!