当前位置: 首页 > news >正文

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

  • “这图是不是糊了?”
  • 以为是样式缺了?试试手动复制
  • 差异在哪?想用对比工具一探究竟……
  • 简单到不能再简单的代码,有问题吗?
  • 最后的真相: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 BeautifulSoupwith 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 部分的混乱。

以此留念,拒绝踩坑。

相关文章:

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

“这图是不是糊了&#xff1f;”以为是样式缺了&#xff1f;试试手动复制差异在哪&#xff1f;想用对比工具一探究竟……简单到不能再简单的代码&#xff0c;有问题吗&#xff1f;最后的真相&#xff1a;viewBox vs viewbox&#xff0c;preserveAspectRatio vs preserveaspectr…...

ai-warp 开源的Platformatic Stackable 与 AI 服务交互

一、软件介绍 文末提供程序和源码下载学习 ai-warp 开源的Platformatic Stackable 与 AI 服务交互 二、用法 npx create-platformaticlatestSelect Application, then platformatic/ai-warp 选择 Application&#xff08;应用程序 &#xff09;&#xff0c;然后选择 platfor…...

AI比人脑更强,因为被植入思维模型【53】反熵增思维模型

giszz的理解&#xff1a;熵用来形容系统的混乱程度。熵增就是从有序到无序&#xff0c;反熵增就是从无序到有序。其实阴阳二级&#xff0c;世界总是在变化之中。保持清醒的头脑&#xff0c;认识到当前是有序还是无序的&#xff0c;如何改变&#xff0c;让事物向着自己希望的方式…...

408 计算机网络 知识点记忆(8)

前言 本文基于王道考研课程与湖科大计算机网络课程教学内容&#xff0c;系统梳理核心知识记忆点和框架&#xff0c;既为个人复习沉淀思考&#xff0c;亦希望能与同行者互助共进。&#xff08;PS&#xff1a;后续将持续迭代优化细节&#xff09; 往期内容 408 计算机网络 知识…...

DDR管脚违例

管脚验证&#xff0c;出现上述违例 上述警告是IO电平配置存在冲突&#xff0c;主要原因是这里配置没有显示电平特性&#xff0c;那么vivado工具默认是生成IP的底层的代码中自带的XDC的电平&#xff0c;这个就冲突了。 出现这个的主要原因还是vivado某个版本工具存在漏洞&#x…...

25年河南事业单位报名详细流程图解

1.报名时间为2025年4月11日9∶00至4月17日17∶00&#xff1b; 2.网上缴费&#xff1a;2025年4月12日9:00至4月18日17:00&#xff1b; 3.打印准考证&#xff1a;2025年5月12日9∶00至5月18日14∶30&#xff1b; 4.笔试时间&#xff1a;2025年5月18日&#xff1b; 5.报名方式…...

一维差分数组

2.一维差分 - 蓝桥云课 问题描述 给定一个长度为 n 的序列 a。 再给定 m 组操作&#xff0c;每次操作给定 3 个正整数 l, r, d&#xff0c;表示对 a_{l} 到 a_{r} 中的所有数增加 d。 最终输出操作结束后的序列 a。 ​​Update​​: 由于评测机过快&#xff0c;n, m 于 20…...

Windows 录音格式为什么是 M4A?M4A 怎样转为 MP3 格式

M4A 格式凭借其高效的压缩技术和卓越的音质表现脱颖而出&#xff0c;成为了包括 Windows 在内的众多操作系统默认的录音格式选择。然而&#xff0c;尽管 M4A 格式拥有诸多优点&#xff0c;不同的应用场景有时需要将这些文件转换为其他格式以满足特定需求。 本文将探讨 M4A 格式…...

【KWDB 创作者计划】第一卷:基础架构篇

以下是KWDB技术白皮书第一卷&#xff1a;基础架构篇的完整内容展示&#xff0c;包含要求的三个核心章节的深度解析。我们将以技术严谨性结合可读性的方式呈现&#xff0c;实际交付时会进一步扩展示意图和代码示例。 目录 ​KWDB技术白皮书卷一&#xff1a;基础架构篇 ​1. 数…...

分享一些使用DeepSeek的实际案例

文章目录 前言职场办公领域生活领域学习教育领域商业领域技术开发领域 前言 以下是一些使用 DeepSeek 的实际案例&#xff1a; DeepSeek使用手册资源链接&#xff1a;https://pan.quark.cn/s/fa502d9eaee1 职场办公领域 行业竞品分析&#xff1a;刚入职的小李被领导要求一天内…...

华清远见成都中心嵌入式学习总结

一、Linux 基础入门 课程首先介绍了 Linux 系统的六大特性&#xff0c;包括开源、免费、可裁剪等核心优势。重点讲解了文件系统结构&#xff0c;强调根目录&#xff08;/&#xff09;作为唯一入口的树状结构。通过实操学习了 pwd、ls、cd 等基础命令&#xff0c;掌握了绝对路径…...

【13】数据结构之树结构篇章

目录标题 树Tree树的定义树的基本概念树的存储结构双亲表示法孩子表示法孩子兄弟表示法 二叉树二叉树与度不超过&#xff12;的普通树的不同之处二叉树的基本形态二叉树的分类二叉树的性质 二叉树的顺序存储二叉树的链式存储二叉树的链式存储的结点结构树的遍历先序遍历中序遍历…...

SAP GUI 显示SAP UI5应用,并实现SSO统一登陆

想用SAP UI5 做一写界面&#xff0c;又不想给用户用标准的Fiori APP怎么办&#xff1f;我觉得可以用可配置物料标准功能的思路&#xff0c;在SAP GUI中显示UI5界面&#xff0c;而不是跳转到浏览器。 代码实现后的效果如下&#xff1a; 1、调用UI5应用&#xff0c;适用于自开发…...

Linux环境变量详解

引言 在Linux系统中&#xff0c;环境变量是一种非常重要的概念&#xff0c;它影响着系统的运行方式和应用程序的行为。无论你是Linux新手还是经验丰富的管理员&#xff0c;深入理解环境变量都能帮助你更高效地使用和管理Linux系统。本文将从基础概念到高级应用&#xff0c;全面…...

【antd + vue】Tree 树形控件:默认展开所有树节点 、点击文字可以“选中/取消选中”节点

一、defaultExpandAll 默认展开所有树节点 1、需求&#xff1a;默认展开所有树节点 2、问题&#xff1a; v-if"data.length"判断的层级不够&#xff0c;只判断到了物理那一层&#xff0c;所以只展开到那一层。 3、原因分析&#xff1a; 默认展开所有树节点, 如果是…...

专题三——二分查找

目录 一、二分查找 1、题目 2、解题思路 3、代码实现 4、时间复杂度 5、朴素二分法的模板总结 二、在排序数组中查找元素的第一个和最后一个位置 1、题目 2、题目解析 3、代码实现 4、 模板总结&#xff08;重点&#xff09; 三、x的算法平方根 1、题目 2、 题目解…...

从零实现HTTP服务器

响应&#xff1a; 第一部分测试代码&#xff0c;读取请求 Makefile binhttpserver #生成的可执行程序 ccg #编译器名称 LD_FLAGS-stdc11 -lpthread #-DDEBUG1 #链接选项 srcmain.cc$(bin):$(src)$(cc) -o $ $^ $(LD_FLAGS).PHONY:clean clean:rm -f $(bin) 1111111 main.cc…...

智能检索知识库​

一、智能检索知识库作用 1. 提升信息检索效率&#xff0c;降低人力成本 快速获取精准答案&#xff1a;员工无需手动翻阅大量文档&#xff08;如产品手册、合同、技术文档&#xff09;&#xff0c;直接通过自然语言提问获取答案。 减少重复性工作&#xff1a;HR、客服、技…...

北斗导航 | 接收机自主完好性监测(RAIM)算法学习思路总结及其算法研究:理论、实现与验证

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 接收机自主完好性监测学习思路 壹、学习思路贰、理论、实现与验证1. 引…...

无法读取库伦值文件节点解决方案

读取库伦值的目的是为了换算成电流&#xff0c;量化场景功耗用途 1.报错日志 /power_log/debuglogger$ adb shell dmesg | grep -Ei "avc..system_server"[ 79.942272] logd.auditd: type1400 audit(1744279324.832:7149): avc: denied { read } for comm"…...

OCR API识别对比

OCR 识别DEMO OCR识别 demo 文档由来 最开始想使用百度开源的 paddlepaddle大模型 研究了几天&#xff0c;发现表格识别会跨行&#xff0c;手写识别的也不很准确。最终还是得使用现成提供的api。。 文档说明 三个体验下来 腾讯的识别度比较高&#xff0c;不论是手写还是识别表…...

高速电路设计概述

1.1 低速设计和高速设计的例子 本节通过一个简单的例子&#xff0c;探讨高速电路设计相对于低速电路设计需要考虑哪些不同的问题。希望读者通过本例&#xff0c;对高速电路设计建立一个表象的认识。至于高速电路设计中各方面的设计要点&#xff0c;将在后续章节展开详细的讨论…...

Keil C51中32位变量赋值异常问题分析与解决

Keil C51中32位变量赋值异常问题分析与解决 问题描述 在使用Keil5对51单片机进行编程时&#xff0c;遇到一个32位变量赋值不正确的问题。具体代码如下&#xff1a; typedef unsigned long uint32;g_Flow_Time (uint32)Storage[2] << 24 | Storage[3] << 16 | S…...

python工程中的包管理(requirements.txt)

pip install -r requirements.txtpython工程通过requirements.txt来管理依赖库版本&#xff0c;上述命令&#xff0c;可以一把安装依赖库&#xff0c;类似java中maven的pom.xml文件。 参考 [](...

用Python修改字体字形与提取矢量数据:fontTools实战指南

字体设计与分析是NLP和视觉领域的交叉应用&#xff0c;而**fontTools** 是一款强大的Python库&#xff0c;可以让我们直接操作字体文件的底层结构。本文将通过两个实用函数&#xff0c;展示如何修改特定字形和提取所有字形的矢量数据&#xff0c;帮助开发者快速上手字体编辑与分…...

数据库守护神-WAL机制

什么是WAL机制&#xff1f; WAL&#xff08;Write-Ahead Logging&#xff0c;预写日志&#xff09;是一种保证数据库操作原子性和持久性的核心机制。其核心原则可概括为&#xff1a; 任何数据修改操作&#xff0c;必须在对应的日志记录持久化到磁盘之后&#xff0c;才能将实际…...

[MySQL]数据库与表创建

欢迎来到啾啾的博客&#x1f431;。 这是一个致力于构建完善 Java 程序员知识体系的博客&#x1f4da;。 它记录学习点滴&#xff0c;分享工作思考和实用技巧&#xff0c;偶尔也分享一些杂谈&#x1f4ac;。 欢迎评论交流&#xff0c;感谢您的阅读&#x1f604;。 本篇简单记录…...

工作记录 2015-05-27

工作记录 2015-05-27 序号 工作 相关人员 1 修改了指定短语的大小写的处理。 取消了一些逗号的处理。 郝 另&#xff1a; iCDA更新到了190的D:\Temp\CHTeam\iCDA_20150527下了 修改的文件&#xff1a; bin目录下是程序。 0223目录下是0223的一些设置和关键字。 更新…...

嵌入式汇编语言从小白到入门:从零开始的底层编程之旅

嵌入式汇编语言从小白到入门:从零开始的底层编程之旅 汇编语言作为最接近机器语言的编程方式,在嵌入式开发中扮演着不可替代的角色。本文将带你从零开始,逐步掌握嵌入式汇编语言的核心概念和实践技巧,最终能够独立编写简单的汇编程序并与C语言混合编程。 一、汇编语言与嵌…...

GPIO_ReadInputData和GPIO_ReadInputDataBit区别

目录 1、GPIO_ReadInputData: 2、GPIO_ReadInputDataBit: 总结 GPIO_ReadInputData 和 GPIO_ReadInputDataBit 是两个函数&#xff0c;通常用于读取微控制器GPIO&#xff08;通用输入输出&#xff09;引脚的输入状态&#xff0c;特别是在STM32系列微控制器中。它们之间的主要…...

不使用docker在本地安装与配置RAGFlow

RAGFlow 本地安装与配置(非docker方式) 一. 运行环境 windows10 CPU i7-12700F 2.10GHz内存 32GGPU RTX 4060 Ti 8G wsl 2 Ubuntu-22.04 1. 防火墙配置 wsl默认访问windows的本机服务需要配置防火墙&#xff0c;否则访问会失败。 windows10的防火墙配置&#xff1a; 打…...

sysfs 设备模型

介绍 Sysfs 设备文件系统与proc是同一类的文件系统&#xff0c;基于ramfs实现的内存文件系统。 1.1 为什么会有 sysfs&#xff1f;procfs 的局限性&#xff1a; 早期&#xff0c;Linux 使用 procfs 来提供内核与用户空间的交互接口。但 procfs 的设计不够层次化&#xff0c;设…...

彩讯携Rich AICloud与一体机智算解决方案亮相中国移动云智算大会

2025年4月10日&#xff0c;2025中国移动云智算大会在苏州盛大开幕&#xff0c;本次大会以“由云向智 共绘算网新生态”为主题&#xff0c;与会嘉宾围绕算力展开重点探讨。 大会现场特设区域展出各参会单位的最新算力成果&#xff0c;作为中国移动重要合作伙伴&#xff0c;彩讯…...

js触发隐式类型转换的场景

JavaScript 的隐式类型转换&#xff08;Implicit Type Coercion&#xff09;会在某些操作或上下文中自动触发&#xff0c;将值从一种类型转换为另一种类型。以下是常见的触发场景&#xff1a; 1. 使用 &#xff08;宽松相等&#xff09;比较时 会尝试将两边的值转换为相同类型后…...

《AI大模型应知应会100篇》第9篇:大模型的推理能力:原理与实现

第9篇&#xff1a;大模型的推理能力&#xff1a;原理与实现 摘要 近年来&#xff0c;随着大语言模型&#xff08;LLM&#xff09;的快速发展&#xff0c;其推理能力逐渐成为研究和应用中的热点话题。这些模型不仅能够生成流畅的文本&#xff0c;还能在一定程度上进行逻辑推理、…...

PODS_ROOT、BUILT_PRODUCTS_DIR和SRCROOT有什么区别

在 iOS/macOS 开发中&#xff0c;${PODS_ROOT}、${BUILT_PRODUCTS_DIR} 和 ${SRCROOT} 是三个核心的 Xcode 环境变量&#xff0c;它们的区别主要体现在 目录层级、内容归属 和 生命周期 上。以下是结构化对比和具体示例&#xff1a; 1. 定义与作用域对比 变量全称指向路径管理…...

Elasticsearch 系列专题 - 第六篇:高级功能与生态系统

Elasticsearch 不仅是一个强大的搜索引擎,还提供了高级功能和丰富的生态系统支持。本篇将深入探讨这些特性,并介绍如何与其他工具协同工作。 1. 高级特性 1.1 跨集群搜索(Cross-Cluster Search) 跨集群搜索允许查询多个独立集群的数据,适用于分布式系统。 配置远程集群:…...

python的web框架flask(hello,world版)

问题 最近需要基于一个开源项目进行二次开发&#xff0c;但是&#xff0c;现在的我主修java&#xff0c;从来没有接触过python的web开发。所以&#xff0c;我现在需要学习一下flask的hello&#xff0c;world。 python版本选择 通过这个Python版本状态页面Status of Python v…...

Vue学习笔记 - 逻辑复用 - 组合式函数

昨天参加了次视频面试&#xff0c;慢慢可以查漏补缺,继续学习Vue相关的知识&#xff0c;考虑找个实际的开源项目。 逻辑复用 组合式函数 在 Vue 应用的概念中&#xff0c;“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。 无状态的…...

Caffeine的两种实现方式

咱们来具体对比一下你之前给的这段配置代码&#x1f447;&#xff1a; java Configuration EnableCaching public class CacheConfig { Bean public CacheManager cacheManager() { CaffeineCacheManager manager new CaffeineCacheManager("myCache"); manager.…...

单细胞Seurat标准分析流程R语言封装

单细胞Seurat标准分析流程R语言封装 数据预处理与质控(线粒体基因比例计算、QC图表生成)标准化与高变基因筛选PCA/UMAP降维与聚类分析 差异表达分析模块自动化输出PNG可视化图表(质控小提琴图、UMAP聚类图)结果将保存在results/和figures/目录下(RDS对象、差异基因CSV表格…...

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

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

航顺HK32M070电钻解决方案:驱动未来,掌控无限可能

一、市场规模与增长&#xff1a;电动工具行业持续扩容&#xff0c;电钻需求强劲 全球电动工具市场规模近年来保持稳定增长&#xff0c;2023年市场规模已达288.5亿美元&#xff0c;预计2024年将突破304.9亿美元&#xff0c;年复合增长率达6.9%。中国市场表现尤为亮眼&#xff0…...

关于nacos注册的服务的ip异常导致网关路由失败的问题

文章目录 关于nacos注册的服务的ip异常导致网关路由失败的问题相关处理方案为方案一:手动指定服务注册的 IP 地址方法二&#xff1a;设置优先使用的网络段方法三&#xff1a;指定网络接口方法四&#xff1a;忽略特定的网卡 备注 关于nacos注册的服务的ip异常导致网关路由失败的…...

UI测试流程与关键注意点解析

在当今以用户体验为核心的数字时代&#xff0c;用户界面(UI)作为软件与用户交互的直接窗口&#xff0c;其质量直接影响着产品的成败。UI测试作为软件测试的重要组成部分&#xff0c;确保应用程序不仅功能完善&#xff0c;而且在视觉呈现和交互体验上也能满足用户期望。 作为软…...

从零开始构建智能聊天机器人:Rasa与ChatGPT API实战教程

引言&#xff1a;AI对话系统的时代机遇 在数字化转型浪潮中&#xff0c;聊天机器人已成为连接用户与服务的关键纽带。无论是客服系统中的724小时即时响应&#xff0c;还是智能家居中的语音交互&#xff0c;聊天机器人正在重塑人机交互方式。本文将通过详细教程&#xff0c;手把…...

SSM aop切面编程的学习

面向切面的AOP编程的引入&#xff1a; 1. 代码缺陷 - 非核心代码对核心业务功能有干扰&#xff0c;导致程序员在开发核心业务功能时分散了精力 - 附加功能代码重复&#xff0c;分散在各个业务功能方法中&#xff01;冗余&#xff0c;且不方便统一维护&#xff01; 2. 解决思路 …...

Zen 5白色装机优选,华硕X870 AYW GAMING WIFI W主板来了!

华硕X870/X870E系列主板再次迎来新成员——华硕X870 AYW GAMING WIFI W主板正式发售&#xff01;专为追求高性价比游戏玩家而量身打造&#xff0c;延续AYW系列经典SPACE太空元素&#xff0c;配合大面积银白色散热装甲&#xff0c;打造出了极具金属质感和科技感的外观&#xff0…...

第Y1周:调用YOLOv5官方权重进行检测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 1、前言2、下载源码3、运行代码 1、前言 YOLOv5分为YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x四个版本&#xff0c;这里以YOLOv5s为例。 2、下载源码 安…...

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

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