BeautifulSoup 踩坑笔记:SVG 显示异常的真正原因

news2025/4/15 12:19:57
  • “这图是不是糊了?”
  • 以为是样式缺了?试试手动复制
  • 差异在哪?想用对比工具一探究竟……
  • 简单到不能再简单的代码,有问题吗?
  • 最后的真相:viewBox vs viewbox,preserveAspectRatio vs preserveaspectratio
  • 别急,问题其实出在 parser 上
  • 正确做法:用 xml parser!

我有几个网页需要处理,想从中提取出 SVG 图单独保存。操作也很简单,网页保存为 .html 后,用 Python + BeautifulSoup 提取 <svg> 标签,保存为 .svg 文件。

一切看起来都很顺利,代码跑起来没报错,文件也生成了。但打开 SVG 一看,总感觉哪儿不太对劲

“这图是不是糊了?”

那是一种怎么形容呢……“有点糊”的感觉。轮廓线条模糊了,缩放好像不太灵,反正就不像原网页中那么清晰了。

svg compare

图中左侧是 BeautifulSoup 提取的结果,右侧是网页中原始的显示效果,看着还是非常明显。

以为是样式缺了?试试手动复制

起初我以为可能是 SVG 引用了网页外部的样式表,所以通过代码提取出来后,没法正确渲染。

那我就直接从 HTML 源码里把 <svg> 标签复制出来,保存成 .svg 文件。结果一打开:显示完全正常!

这说明:SVG 并没有依赖外部样式,问题出在提取方式上。

差异在哪?想用对比工具一探究竟……

想到这里,我打算用 Beyond Compare 这种工具来看看手动提取和代码提取的 SVG 文件有啥不同。

结果发现:属性的顺序被 BeautifulSoup 改了个遍,标签缩进也被重新排过了。

这下比对也不好看了,完全对不上。搞得我直接放弃用工具对比,只能开始回头怀疑自己的代码:

简单到不能再简单的代码,有问题吗?

下面是我最开始的代码,提取 SVG 并保存:

from bs4 import BeautifulSoup

with open('42e1.html', 'r', encoding='utf-8') as file:
    html_content = file.read()

soup = BeautifulSoup(html_content)
svg = soup.find('svg')

if svg:
    svg_string = svg.prettify()
    with open('extracted_42e1.svg', 'w', encoding='utf-8') as f:
        f.write(svg_string)

代码非常简单,难道是 .prettify() 的锅?它会不会在格式化的时候,修改了什么属性?

我试了几个 formatter 参数,也没解决问题,结果还是老样子。

最后的真相:viewBox vs viewbox,preserveAspectRatio vs preserveaspectratio

没辙了,我只能回到老老实实肉眼对比。

我皱着眉头盯着 Beyond Compare,看着它标红的地方……一开始我还没看出来。

结果,居然只是属性名变成了小写:

  • viewBoxviewbox
  • preserveAspectRatiopreserveaspectratio

嘴里飙出了一句国粹之后,我第一反应是直接暴力补丁:

svg_content = svg_content.replace("viewbox", "viewBox")
svg_content = svg_content.replace("preserveaspectratio", "preserveAspectRatio")

还一度想给 BeautifulSoup 提个 issue:你咋连大小写都搞不清?

别急,问题其实出在 parser 上

冷静之后,我想:不应该啊,BeautifulSoup 这么成熟的库,不可能犯这种低级错误。

于是去查了查文档——果然问题不在 BeautifulSoup 本身,而在于我用的解析器。

默认的 html.parser 是按照 HTML 规范设计的,它会把标签名和属性名全部转换为小写,这是符合 HTML 标准的。

但问题来了,SVG 是 XML 子集,属性名是区分大小写的

换句话说,我在解析 XML 的时候用了 HTML 的工具,所以出问题了

正确做法:用 xml parser!

所以解决方法其实很简单,只需要:

soup = BeautifulSoup(html_content, "xml")

这样,viewBoxpreserveAspectRatio 就能原封不动地保留下来,SVG 也就恢复正常了。结局也算是皆大欢喜了。

补一句

  • 如果专门要处理 SVG、MathML、RSS 等 XML 内容,请用 xmllxml-xml

  • 如果要处理 HTML 页面,继续用 html.parser 是对的,因为使用 xml 解析可能会造成 html 部分的混乱。

以此留念,拒绝踩坑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【browser-use+deepseek】实现简单的web-ui自动化

browser-use Web-UI 一、browser-use是什么 Browser Use 是一款开源Python库&#xff0c;专为大语言模型设计的智能浏览器工具&#xff0c;目的是让 AI 能够像人类一样自然地浏览和操作网页。它支持多标签页管理、视觉识别、内容提取&#xff0c;并能记录和重复执行特定动作。…

MOS管的发热原因和解决办法

发热来源 如上图&#xff0c;MOS管的工作状态有4种情况&#xff0c;分别是开通过程&#xff0c;导通过程&#xff0c;关断过程和截止过程。 导致发热的损耗主要有两种&#xff1a;开关损耗、导通损耗。 导通损耗 导通损耗比较好计算&#xff0c;根据驱动电压VGS值可以得到MOS…

科技项目验收测试怎么做?验收测试报告如何获取?

科技项目从研发到上市需要一个很长的周期&#xff0c;并且在上市之前还有一个至关重要的交付过程&#xff0c;那就是项目验收&#xff0c;验收需要通过验收测试来呈现。科技项目验收测试是确保项目成功交付的关键步骤&#xff0c;那么是如何进行的呢?企事业单位想要获取科技项…

AutoEval:现实世界中通才机器人操作策略的自主评估

25年3月来自 UC Berkeley 和 Nvidia 的论文“AutoEval: Autonomous Evaluation of Generalist Robot Manipulation Policies in the Real World”。 可规模化且可复现的策略评估一直是机器人学习领域长期存在的挑战。评估对于评估进展和构建更优策略至关重要&#xff0c;但在现…

基于SSM框架的房屋租赁小程序开发与实现

概述 一个基于SSM框架开发的微信小程序房屋租赁管理系统&#xff0c;该项目实现了用户管理、中介管理、房源信息管理等核心功能。 主要内容 一、管理员模块功能实现 ​​用户管理​​ 管理员可对通过微信小程序注册的用户信息进行修改和删除操作&#xff0c;确保用户数据的准…

oracle 表空间(Tablespace)

在 Oracle 11g 中&#xff0c;表空间&#xff08;Tablespace&#xff09; 是数据库存储架构的核心逻辑单元&#xff0c;其原理基于 逻辑存储与物理存储的分离&#xff0c;通过分层管理数据文件、段&#xff08;Segment&#xff09;、区&#xff08;Extent&#xff09;和数据块&…

基于YOLOv8的机场跑道异物检测识别系统:提升航空安全的新一代解决方案(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 机场跑道异物检测领域概述 机场跑道异物(Foreign Object Debris, FOD)是指存在于机场跑道、滑行道等关…

Android学习总结之OKHttp拦截器和缓存

深入理解 OkHttp 拦截器 1. 拦截器接口详解 Interceptor 接口是自定义拦截器的基础&#xff0c;它仅包含一个抽象方法 intercept。以下是对该方法参数和返回值的详细解释&#xff1a; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import…

Wincc管对象的使用

Wincc管对象的使用 管对象的调用多边形管T形管双T形管管弯头管道大小调整 管对象的调用 打开【图形编辑器】 多边形管 多边形管如下&#xff1a; 一根管子的顶点数是两个&#xff0c;如果修改顶点数&#xff0c;管子就有多少个端点。 修改顶点数为5 此时点击端点然后拖动&#…

Linux-----驱动

一、内核驱动与启动流程 1. Linux内核驱动 Nor Flash: 可线性访问&#xff0c;有专门的数据及地址总线&#xff08;与内存访问方式相同&#xff09;。 Nand Flash: 不可线性访问&#xff0c;访问需要控制逻辑&#xff08;软件&#xff09;。 2. Linux启动流程 ARM架构: IRAM…

问问lua怎么写DeepSeek,,,,,

很坦白说&#xff0c;这十年&#xff0c;我几乎没办法从互联网找到这个这样的代码&#xff0c;互联网引擎找不到&#xff0c;我也没有很大的“追求”要传承&#xff0c;或者要宣传什么&#xff1b;直到DeepSeek的出现 兄弟&#xff0c;Deepseek现在已经比你更了解你楼下的超市…

基于神经环路的神经调控可增强遗忘型轻度认知障碍患者的延迟回忆能力

简要总结 这篇文章提出了一种名为CcSi-MHAHGEL的框架&#xff0c;用于基于多站点、多图谱fMRI的功能连接网络&#xff08;FCN&#xff09;分析&#xff0c;以辅助自闭症谱系障碍&#xff08;ASD&#xff09;的识别。该框架通过多视图超边感知的超图嵌入学习方法&#xff0c;整合…

C++学习之ORACLE③

1.集合运算符 查询部门号是10和20的员工信息&#xff1a; &#xff1f;思考有几种方式解决该问题 &#xff1f; SQL> select * from emp where deptno in(10, 20) SQL> select * from emp where deptno10 or deptno20 集合运算&#xff1a; Select * from emp …

UniAD:自动驾驶的统一架构 - 创新与挑战并存

引言 自动驾驶技术正经历一场架构革命。传统上&#xff0c;自动驾驶系统采用模块化设计&#xff0c;将感知、预测和规划分离为独立组件。而上海人工智能实验室的OpenDriveLab团队提出的UniAD&#xff08;Unified Autonomous Driving&#xff09;则尝试将这些任务整合到一个统一…

transformers 中的 input_ids 和 labels 是什么

transformers 中的 input_ids 和 labels 是什么 input_ids 是输入文本的数字化表示,而 labels 是模型训练的目标值 在自然语言处理(NLP)和使用 transformers 库进行模型训练时,tokenizer = AutoTokenizer.from_pretrained(model_path) 这行代码是用于从预训练模型路径加载…

各种排序思路及实现

目录 1.排序概念常见的排序算法 2.常见排序算法实现&#xff08;1&#xff09;插入排序直接插入排序希尔排序&#xff08;缩小增量排序&#xff09; &#xff08;2&#xff09;选择排序直接选择排序堆排序 &#xff08;3&#xff09;交换排序冒泡排序快速排序&#xff08;hoare…

golang 采用use-go/onvif获取RTSP流

采用https://github.com/use-go/onvif得到完整的RTSP流的地址 全局变量UseGoMain 函数GetDeviceInformation 函数GetRTSPUri 函数 全局变量 这些变量用来设定 ONVIF 设备的连接信息&#xff0c;包含设备地址、用户名和密码 var deviceXaddr "*92.1*8.11*.12*:80" …

【北京市小客车调控网站-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

西湖大学团队开源SaProt等多款蛋白质语言模型,覆盖结构功能预测/跨模态信息搜索/氨基酸序列设计等

2025 年 3 月 22—23 日&#xff0c;上海交通大学「AI 蛋白质设计峰会」正式举行。 本次峰会汇聚了来自清华大学、北京大学、复旦大学、浙江大学、厦门大学等知名高校的 300 多位专家学者&#xff0c;以及 200 余位行业领军企业代表和技术研发人员&#xff0c;深入探讨了 AI 在…

一个批量文件Dos2Unix程序(Microsoft Store,开源)

这个程序可以把整个目录的文本文件改成UNIX格式&#xff0c;源码是用C#写的。 目录 一、从Microsoft Store安装 二、从github获取源码 三、功能介绍 3.1 运行 3.2 浏览 3.3 转换 3.4 转换&#xff08;无列表&#xff09; 3.5 取消 3.6 帮助 四、源码解读 五、讨论和…