无法直接用requests获取SVG数据,因其由JS动态渲染;应优先分析XHR请求或JS变量提取数据,其次用Playwright等待并抓取渲染后SVG,再通过data-*属性等可靠方式解析数值。

直接读取网页源码拿不到SVG数据,因为它是JavaScript渲染的
浏览器里看到的SVG图表,往往由前端JS库(如D3.js、Chart.js)在页面加载后动态插入DOM。用requests.get()获取的原始HTML里通常只有空容器(比如<div id="chart"></div>),没有<svg>标签或坐标数据。硬解析HTML源码会失败。
解决思路只有两个:要么模拟浏览器执行JS,要么逆向分析JS的数据加载逻辑。前者稳定但重;后者轻量但依赖站点结构是否暴露数据接口。
- 优先检查Network面板中XHR/Fetch请求——很多图表数据是通过AJAX单独拉取的JSON,比渲染逻辑简单得多
- 若数据藏在JS变量里(如
window.__CHART_DATA__),可配合re.search(r'window\.__CHART_DATA__\s*=\s*(\{.*?\});', html)提取,但要注意转义和JSON格式合法性 - 避免盲目用Selenium:启动浏览器开销大,且容易被反爬触发验证码或IP封禁
用Playwright或Pyppeteer抓取渲染后的SVG内容更可靠
比起Selenium,Playwright对现代JS支持更好、启动更快,且能精准等待SVG节点出现。关键不是“等页面加载完”,而是等特定<svg>元素挂载完成。
示例代码片段:
立即学习“Python免费学习笔记(深入)”;
from playwright.sync_api import sync_playwright
<p>with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('<a href="https://www.php.cn/link/13128f39fb3e7f95638f40923a83d453">https://www.php.cn/link/13128f39fb3e7f95638f40923a83d453</a>')</p><h1>等待SVG容器存在,再等其中至少一个<path>或<circle>渲染出来</h1><pre class='brush:python;toolbar:false;'>page.wait_for_selector('svg', timeout=10000)
page.wait_for_selector('svg path, svg circle', timeout=5000)
svg_html = page.inner_html('svg')
browser.close()</pre>-
wait_for_selector必须指定具体选择器,不能只等svg——有些页面先占位再填充,svg标签存在但内部为空 - 如果SVG是用
<use xlink:href="#template">引用符号,需额外调用page.content()并确保base URL正确,否则xlink:href解析失败 - 某些站点使用Web Components(如
<custom-chart>),需先page.evaluate("document.querySelector('custom-chart').render()")手动触发渲染
提取SVG中的数值数据要绕过视觉编码陷阱
SVG本身不直接存“销售额=120万”,而是用<rect x="100" y="200" width="40" height="80">这类坐标+尺寸表达。把像素值还原成业务数值,必须知道图表的坐标系映射规则。
- 先定位坐标轴元素:
g.axis.x或g.tick text,从中提取刻度文本(如“Jan”、“Feb”)和对应transform属性里的位置 - 柱状图高度常与数值线性相关,但需确认Y轴是否倒置(SVG原点在左上角,
y增大向下);折线图则要按d属性解析贝塞尔路径或折线点序列 - 警惕缩放/平移变换:
<g transform="scale(1.2) translate(50, 30)">会影响所有子元素坐标,需递归计算最终位置 - 不要依赖
getBBox()——它返回的是渲染后边界,可能含padding或stroke宽度,误差可达几个像素
遇到内联样式或CSS类名干扰时,优先用属性而非样式提取
SVG元素常通过fill="#ff6b6b"或class="bar-active"控制外观,但这些跟数据无关。真正承载信息的是data-* 属性(如data-value="42")、aria-label或title子元素。
- 检查
svg g bar rect是否有data-value、data-category等自定义属性,这是最干净的数据通道 - 若只有
title标签,用elem.find('title').text提取(注意部分站点用<desc>替代) - 避免用
style="fill: red"反推分类——颜色可能随主题切换,且无标准化映射表 - 某些图表将数值编码进
id(如id="bar-2023-Q3"),需结合上下文正则匹配,但稳定性差,仅作备用方案
实际处理时,多数失败源于假设“SVG结构固定”。真实站点会频繁更新JS库版本,class名、data-属性名、甚至SVG嵌套层级都可能变化。留一版基于XPath或CSS选择器的fallback逻辑,比反复重写解析器更省时间。


















