SVG映射是网页反爬手段,通过SVG元素与CSS坐标偏移实现字符隐藏,解析关键在于还原字符与坐标的映射关系,而非解密。

SVG映射字符加密不是标准加密算法,而是网页反爬常见手段:把真实文字拆成 <text></text> 或 <use></use> 元素,用 <defs></defs> 里的 <symbol></symbol> 或 <g></g> 定义字形偏移,再靠 CSS 或 transform 拼出可读文本。解析关键不在“解密”,而在还原坐标与字符的映射关系。
定位 SVG 字符映射定义位置
这类混淆通常集中在页面底部或独立 <svg></svg> 块中,且常带特定 class(如 svg-text、icon-font)或隐藏样式(display:none)。不能只看 visible 元素——很多映射定义本身不可见,只被 <use></use> 引用。
- 用
BeautifulSoup搜索所有<svg></svg>,再逐个查<defs></defs>子节点,重点看<symbol></symbol>、<g id="..."></g>、<text id="..."></text> - 注意
<use href="#xxx"></use>中的#xxx,它指向的 ID 就是映射单元;href 值可能含空格或编码,需用urllib.parse.unquote()清洗 - 有些站点用内联
<style></style>控制transform: translate(x,y),此时需同时提取 CSS 规则和对应元素的class
提取字符与坐标的映射关系
映射方式分两类:一类是每个 <symbol></symbol> 或 <g></g> 内含一个字符(如 <text x="10" y="20">A</text>),另一类是单个 <text></text> 包含多个字符但用 <tspan></tspan> 分段并设置不同 dx/dy。必须统一转为「字符 → (x, y)」键值对,否则无法对齐显示位置。
- 对
<symbol></symbol>:取其id为 key,遍历子<text></text>的text_content()和x/y属性(注意单位,常见 px、em,需归一化) - 对
<tspan></tspan>:父<text></text>的x/y是起点,每个<tspan></tspan>的dx/dy是相对偏移,累加得绝对坐标 - 若出现
transform="translate(100,50)",需解析数值并加到子元素坐标上——别信get("x")返回的原始值,它可能是未变换前的
匹配页面中被混淆的文本元素
目标文本通常以 <use></use>、<text></text> 或带特殊 class 的 <span></span> 形式存在。关键不是“渲染后长什么样”,而是它引用了哪个映射单元、起始坐标是多少。坐标错一位,字符就拼错。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 找
<use></use>:提取href指向的 ID,再从映射表里取对应字符;同时读它的x和y属性——这是该字符在页面上的落点 - 找
<text></text>:若它没有直接文本内容,但含<tspan></tspan>,则按顺序取每个<tspan></tspan>的字符 + 累计坐标 - 若多个
<use></use>共享同一 ID(比如都指向#char-65),说明这是字母 A 的复用;但它们的x不同——这意味着同一个字符在不同位置出现,不能合并处理
处理动态加载和字体 fallback
部分站点用 JS 动态注入 SVG 定义,或依赖 WebFont 加载后才替换 DOM。静态解析 requests.get().text 会漏掉这些。还有站点用 <foreignobject></foreignobject> 嵌 HTML,或混用 Unicode 替换(如 \uE001)+ font-face,这时 SVG 只是备用方案。
- 优先用
selenium或playwright获取完整渲染后 HTML,再喂给BeautifulSoup——但注意等待svg节点出现,别在 DOM 就绪前就抓 - 检查
<style></style>中是否有@font-face定义自定义字体,若有,且文本用该字体显示,那 SVG 映射可能只是降级方案,实际应走字体文件解析(用fonttools读 .woff,查 cmap 表) - 当
<use></use>的href是空字符串或javascript:void(0),大概率是 JS 运行时重写过,必须走浏览器环境
真正难的不是解析 SVG 结构,而是判断哪些坐标该累加、哪些该覆盖、哪些要忽略(比如装饰性线条的 <path></path>)。一个 transform 里嵌三层 scale 和 rotate,再叠 viewBox 缩放,手动算像素位置极易出错。建议先用浏览器 DevTools 手动选中一个 <use></use>,看 computed tab 里的最终 transform 矩阵,再决定是否值得写矩阵解析逻辑——多数场景,只取 translate 部分已够用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










