简介:面向Python数据分析与可视化学习者的二氧化碳排放趋势大屏工程,重点解决从原始CSV到交互式Web看板的完整链路问题。工程实践覆盖数据导入、清洗与缺失值处理,利用pandas完成时间序列重采样和地区分组统计,并配合matplotlib/seaborn绘制排放趋势图、柱状对比图;进一步通过Streamlit构建大屏,支持动态选择时间段与国家地区,多图联动直观展示排放变化与区域差异,适用课程设计、科研报告或环保科普等场景。压缩包共3个文件,包含2份CSV数据源(一份为历史总览、一份按国家/地区细分)和1个Python主脚本,整体约1.83MB,轻量紧凑,代码结构清晰,便于逐行理解。已有1495人学习,适合具备基础Python语法、希望进阶数据分析与可视化的开发者;工程稍作改造即可迁移至其他环境指标的大屏展示,是一份上手快、可扩展的实战参考。
1. 一块二氧化碳可视化大屏,真正难的不是画图
接到「用 python 制作可视化大屏,分析二氧化碳排放趋势和影响」这个需求,很多人第一反应是去找大屏模板、调颜色、加特效。我做过几轮之后可以给你交个底:图表渲染只占两成工作量,剩下八成全押在两件事上——数据口径能不能对齐,趋势与影响分析经不经得起被追问。大屏投到指挥中心墙上,第一眼是视觉,第二眼是数字,第三眼就是问题:你这个总量是万吨还是亿吨?增速算的是同比还是环比?脱钩指数到底是变大还是变小了?
这篇文章按我自己的落地路径来写:先理顺碳排放数据的口径和趋势算法,再选型确定用 pyecharts 还是前端大屏可视化编辑器,然后带你从一张趋势面积图开始,拼出完整的 1920×1080 大屏,最后把内网部署、分辨率适配、数据刷新这些坑一个个填掉。适合手里有 pandas 基础、需要交付一块真能上墙的碳排看板的人,也适合想评估「这个方向值不值得自己投入」的团队。
2. 先把二氧化碳数据理顺:三种口径与趋势计算方法
2.1 碳排放数据的三种常见口径
做二氧化碳大屏,第一步不是画图,而是搞清楚数据是什么口径。我做过的项目里,数据通常来自统计年鉴、重点企业报送、环境监测平台或者咨询机构,常见口径有三种。
| 口径 | 核心字段 | 典型单位 | 常见混淆点 |
|---|---|---|---|
| 总量口径 | 区域/全国年度排放总量 | 亿吨 CO2 或万吨 CO2 | 累计值和年度值混用 |
| 结构口径 | 分能源品种、分部门排放 | 万吨 CO2 | 标煤量和排放量混用 |
| 强度口径 | 排放总量 / GDP | 吨 CO2 / 万元 | 用当年价还是不变价 GDP |
总量口径解决「排了多少」的问题,结构口径解决「谁在排」,强度口径解决「排得划不划算」。大屏上把这三层都放进去,才算扣住了标题里的「趋势和影响」。
这里有个新手最容易踩的坑:月度数据出现明显断裂,往往不是排放真的跌了,而是上月末有个「累计值」混进了当月值序列。我一般的做法是拿到数据先不急着画图,先做一次物理检查:按时间排序,算相邻两期差值,超过历史最大月变化的 3 倍就标出来人工核。大屏可以没有花哨动画,但不能有一个让人当场质疑的数字。
2.2 用 pandas 把乱序数据校准成可比较的时间序列
假设你已经有一份 CSV,包含日期、排放量、单位、部门和 GDP。下面这段是数据清洗和年度聚合的骨架,可以直接跑:
import pandas as pd import numpy as np # 读取原始数据,date 列解析成时间类型 df = pd.read_csv("co2_data.csv", parse_dates=["date"]) df = df.sort_values("date").set_index("date") # 统一排放单位到“万吨” # 单位列里常见的有亿吨、万吨、吨,分别换算 df["emission_wt"] = np.where(df["unit"] == "亿吨", df["emission"] * 10000, np.where(df["unit"] == "吨", df["emission"] / 10000, df["emission"])) df["gdp"] = df["gdp"].astype(float) # 按年度聚合,得到该年度总排放和平均GDP year_df = df.resample("YE").agg( emission=("emission_wt", "sum"), gdp=("gdp", "mean") ) # 同比增速:用 pct_change 即可,输出为百分数 year_df["emission_yoy"] = year_df["emission"].pct_change() * 100 # 三年移动平均,平滑掉单年异常波动 year_df["emission_ma3"] = year_df["emission"].rolling( 3, min_periods=1 ).mean()这段代码有两个地方值得盯一下。第一,resample("YE")在 pandas 2.x 里是年终聚合,老版本可能要写"A";如果你的数据是自然年度已经聚合好的,这步可以直接跳过。第二,pct_change()产生的第一个值是 NaN,后面算脱钩指数时记得过滤,别让 NaN 串进大屏 JSON。
rolling(3, min_periods=1)是我必写的参数。min_periods=1保证前面缺数据的年份也有值可看,否则 2015 年那一栏会直接空掉,给前端传 null 时 ECharts 的折线会出现断点,观感很差。
2.3 判断排放趋势:斜率和加速度比「涨了还是跌了」更实用
大屏中间主图通常放总量趋势,但光是「今年比去年多」解决不了判断。CO2 排放最关心的是:趋势方向是上行还是下行,增速是在加快还是在放缓。用numpy.polyfit做一阶和二阶拟合,比单独看某一年波动靠谱得多。
import numpy as np x = np.arange(len(year_df)) # 0,1,2,... 对应年份顺序 y = year_df["emission"].values # 年度排放总量(万吨) # 一阶拟合:y = k1 * x + b1,斜率 k1 代表平均每年增减多少万吨 k1, b1 = np.polyfit(x, y, 1) year_df["trend_line"] = np.polyval([k1, b1], x) # 二阶拟合:y = c2 * x^2 + c1 * x + c0 c2, c1, c0 = np.polyfit(x, y, 2) # 加速度 = 2 * c2,正数表示排放增速在加快,负数表示在放缓 acceleration = 2 * c2逻辑说明:k1的单位是「万吨/年」,比如 k1 = 3200,说明这十年里每年平均比上一年多排放 3200 万吨。c2的正负更有意思——它是二次项的系数,乘以 2 后是二阶导,代表趋势本身的加速度。如果总排放还在涨,但acceleration已经转负,说明涨势收敛,这比「年排放又创新高」这个结论更有汇报价值。
参数提醒:年度数据通常只有 10~30 个点,样本量不大,拟合出来的 R² 可以参考但不值得较真。我的习惯是把趋势线用虚线画出来,并且绝不外推超过两年。领导问「明年多少」时,你可以给区间,但别给精确值——那是预测模型该干的事,不是趋势拟合。
2.4 影响分析:排放强度、部门贡献与脱钩指数
「影响」落到大屏上,不能只写一句「排放影响气候」。我常用三个可计算的量化指标:
# 1. 排放强度:每万元 GDP 对应的排放吨数,越低说明增长质量越高 year_df["intensity"] = year_df["emission"] / year_df["gdp"] # 2. 部门贡献:各行业排放占当年总排放的比例 sector_share = df.groupby([df.index.year, "sector"])["emission_wt"].sum() sector_share = sector_share / sector_share.groupby(level=0).transform("sum") # 3. 脱钩指数:排放增速 与 GDP 增速 的比值 merged = year_df.copy() merged["gdp_yoy"] = merged["gdp"].pct_change() * 100 merged["decoupling"] = merged["emission_yoy"] / merged["gdp_yoy"]脱钩指数的含义值得在图上标清楚:指数大于 1,说明排放增速比经济增速还快,是「高挂钩」;在 0 到 1 之间是「相对脱钩」,经济在增长但排放增速放缓;指数小于 0 且排放增速为负,才是「绝对脱钩」。计算时注意过滤gdp_yoy接近 0 的年份,否则一个除法就能把图炸出天际。
部门贡献适合用堆叠柱状图或占比折线看结构变迁,排放强度适合和 GDP 增速做双轴图。这两个图我会在第 4 章放上大屏。数据这一步做完,后面所有图表都只是把你已经算好的结论可视化,而不是在图表里临时算。
3. 选型:pyecharts 全栈,还是前端大屏可视化编辑器
3.1 两种技术路线的边界
大屏可视化编辑器这几年很火,拖拖拽拽就能出图,确实省事。但回到这个标题——用 python 制作可视化大屏分析二氧化碳排放趋势和影响——你大概率已经有数据清洗和趋势计算写在 Python 里了。与其把算好的结果再手动粘进编辑器,不如考虑两条更顺的路线。
| 维度 | 方案 A:pyecharts 全栈生成 HTML | 方案 B:Python 做接口 + 前端 ECharts |
|---|---|---|
| 学习成本 | 低,只会 Python 也能交付 | 需要一点 HTML/JS 基础 |
| 交付速度 | 当天出第一版 | 前后端联调多花 1~2 天 |
| 实时刷新 | 静态文件,配定时重跑或 meta refresh | 效果好,适合频繁变动数据 |
| 内网离线 | 要把 JS 资源本地化 | 同样要本地化 |
| 二次开发 | 图表配置是 Python 字典 | 前端可以写任意交互 |
我一般怎么选?数据量小、展示为主、团队里没有前端,直接走方案 A,用 pyecharts 的 Page 拖拽布局出大屏,交付一个final.html就能跑。如果后续要做用户权限、多指标切换、真实时数据,老老实实方案 B——Python 只负责吐 JSON,前端 ECharts 负责画。别指望一个编辑器能替你处理「碳排口径随年份调整」这类业务逻辑,它只解决布局问题,解决不了数据可信问题。
3.2 大屏的图表布局与信息层级
大屏不是把所有图塞满就完事。CO2 主题大屏,我建议按「中间结论、左右证据」来排布。中间放最核心的总量趋势,领导进来第一眼就看到排放是在爬升还是掉头;左边放结构证据(能源品种、部门排放),回答「谁在排」;右边放影响证据(排放强度、脱钩指数),回答「排放和经济的关系」。
以 1920×1080 为例,我常用的栅格划分如下:
| 区域 | 占屏宽 | 放什么图 | 信息作用 |
|---|---|---|---|
| 顶部 | 100% | 标题栏、时间范围、关键指标卡 | 一眼定位年份和总量 |
| 左列 | 24% | 能源品种饼图、分部门条形图 | 结构分析 |
| 中间 | 52% | 排放总量趋势面积图 | 核心趋势 |
| 右列 | 24% | 排放强度与 GDP 增速双轴图、脱钩指数 | 影响分析 |
第一次做别贪多,4~5 张图足够。大屏最容易翻车的不是缺图,而是信息过载,每张图都在喊「看我」,最后一块都记不住。
3.3 跑通最小流程需要的文件清单
| 文件 | 作用 |
|---|---|
co2_data.csv | 原始排放和 GDP 数据 |
process_data.py | 清洗、聚合、趋势与脱钩计算 |
build_dashboard.py | 生成图表并拼装大屏 |
co2_dashboard_render.html | 拖拽布局用的中间产物 |
co2_dashboard.html | 最终交付的大屏文件 |
建议把数据清洗和图表生成拆成两个脚本。数据口径调整时只改process_data.py,图表版式调整时只碰build_dashboard.py。混在一起写的脚本,三个月后再看就是黑匣子,改一个数字可能连带图表全崩。
4. 用 pyecharts 制作二氧化碳大屏:从趋势图到整页交付
4.1 环境准备与主题初始化
环境上我没太多可说的,装好 pyecharts 和 pandas 就能开始,vscode 里记得确认 Python 解释器和你 pip 安装包用的是同一个环境。新版本 pyecharts 的导入路径是from pyecharts.charts import Line,老教程里from pyecharts import Line那套已经过时了,照着写会直接 ImportError。
from pyecharts import options as opts from pyecharts.charts import Line, Pie, Bar, Page # 2022 年之后 pyecharts 2.x 的初始化参数 init = opts.InitOpts( width="1200px", height="420px", theme="dark", # 内置暗色主题,适合大屏 bg_color="#0b1220" # 深蓝黑背景,和指挥中心屏幕更搭 )theme="dark"只是给了一个基础暗色底子,实际大屏的配色我通常会自己在每个系列上单独指定,不然系统默认配色会显得「很 pyecharts」。bg_color用纯色深蓝黑#0b1220,比纯黑更有层次,也方便后续在 CSS 里统一背景渐变。
4.2 主图:排放趋势面积图
中间主图用面积图最直观,颜色填充让趋势方向一目了然。下面代码直接承接第 2 章算好的year_df:
years = year_df.index.year.astype(str).tolist() emission_total = year_df["emission"].round(0).tolist() emission_ma3 = year_df["emission_ma3"].round(0).tolist() trend_line = ( Line(init_opts=opts.InitOpts( width="1200px", height="420px", theme="dark", bg_color="#0b1220" )) .add_xaxis(years) .add_yaxis( "排放总量", emission_total, is_smooth=True, symbol="circle", symbol_size=5, areastyle_opts=opts.AreaStyleOpts( opacity=0.35, color="#fbbf24" ), linestyle_opts=opts.LineStyleOpts( width=3, color="#fbbf24" ), label_opts=opts.LabelOpts(is_show=False), ) .add_yaxis( "三年移动平均", emission_ma3, is_smooth=True, symbol="none", linestyle_opts=opts.LineStyleOpts( width=2, color="#38bdf8", type_="dashed" ), label_opts=opts.LabelOpts(is_show=False), ) .set_global_opts( title_opts=opts.TitleOpts( title="二氧化碳排放总量趋势", subtitle="单位:万吨 CO2,虚线为三年移动平均", pos_left="center" ), tooltip_opts=opts.TooltipOpts( trigger="axis", axis_pointer_type="cross" ), datazoom_opts=[opts.DataZoomOpts( range_start=0, range_end=100 )], legend_opts=opts.LegendOpts(pos_top="2%"), xaxis_opts=opts.AxisOpts( name="年份", axislabel_opts=opts.LabelOpts(interval=0) ), yaxis_opts=opts.AxisOpts( name="万吨", splitline_opts=opts.SplitLineOpts(is_show=True) ), ) )逻辑说明:第一条系列是真实排放总量,加了 0.35 透明度的面积填充,用来表达「水位」;第二条是三年移动平均,用虚线,用来表达「趋势」。这两条线叠在一起,观众能同时看到原始波动和趋势方向,比单独一条折线信息量大很多。
参数说明:datazoom_opts默认是开启滚动缩放的手柄,大屏上鼠标操作不频繁,我的习惯是把range_start=0, range_end=100固定住,保证一开始显示全部年份,用户不拖动也不会被截断。symbol="none"让移动平均线不带数据点,避免和图例挤在一起。tooltip用trigger="axis"而不是默认的"item",鼠标扫过时能看到两条线同一年的数据,汇报时体验好很多。
4.3 结构图:能源构成饼图与部门条形图
左侧两张图解决「结构」问题。能源品种排放用玫瑰饼图,部门排放用横向条形图或普通条形图。代码如下:
# 分能源品种排放数据,格式为 [(名称, 值), ...] energy_items = [ ("煤炭", 48210), ("石油", 17520), ("天然气", 9320), ("非化石能源", 6230) ] pie_chart = ( Pie(init_opts=opts.InitOpts( width="520px", height="320px", theme="dark", bg_color="#0b1220" )) .add( "排放量", energy_items, radius=["28%", "68%"], center=["50%", "52%"], rosetype="radius", label_opts=opts.LabelOpts( formatter="{b}\n{d}%", color="#e2e8f0" ) ) .set_global_opts( title_opts=opts.TitleOpts( title="分能源品种排放结构", pos_left="center" ), legend_opts=opts.LegendOpts(pos_bottom="0%") ) ) # 分部门排放 sector_names = ["电力热力", "工业", "交通", "建筑", "居民生活"] sector_values = [42100, 18800, 8200, 3650, 1980] bar_chart = ( Bar(init_opts=opts.InitOpts( width="520px", height="320px", theme="dark", bg_color="#0b1220" )) .add_xaxis(sector_names) .add_yaxis( "排放量", sector_values, category_gap="38%", itemstyle_opts=opts.ItemStyleOpts( color=opts.LinearGradientOpts( xaxis_=0, yaxis_=0, xaxis1_=0, yaxis1_=1, color_list=["#facc15", "#f97316"] ) ), label_opts=opts.LabelOpts( is_show=True, position="top", color="#e2e8f0" ) ) .set_global_opts( title_opts=opts.TitleOpts( title="分部门排放量", pos_left="center" ), xaxis_opts=opts.AxisOpts( axislabel_opts=opts.LabelOpts(rotate=-15) ), yaxis_opts=opts.AxisOpts(name="万吨") ) )参数说明:rosetype="radius"让饼图的半径随数值变化,比普通饼图更能突出煤炭这类大头;formatter="{b}\n{d}%"同时显示名称和百分比,大屏上比图例可读性强。条形图的category_gap="38%"控制柱子间距,间距太小会显得拥挤,太大则浪费横向空间。LinearGradientOpts里的xaxis_和yaxis1_是渐变的起点和终点坐标,我给的是从上到下渐变,适合垂直柱状图。部门超过 8 个时记得给 x 轴加datazoom,否则底下的部门名字会叠成一团。
4.4 影响分析组合图:排放强度与 GDP 增速双轴
右侧放「影响」。最实用的是双轴图:柱状图显示排放强度(吨 CO2/万元 GDP),折线叠加 GDP 增速,一眼看出二者是否脱钩。
from pyecharts.charts import Bar as BarOverlay, Line as LineOverlay intensity_values = year_df["intensity"].round(2).tolist() gdp_growth_values = year_df["gdp_yoy"].round(1).fillna(0).tolist() strength_bar = ( BarOverlay(init_opts=opts.InitOpts( width="520px", height="320px", theme="dark", bg_color="#0b1220" )) .add_xaxis(years) .add_yaxis( "排放强度", intensity_values, yaxis_index=0, color="#10b981", label_opts=opts.LabelOpts(is_show=False) ) .extend_axis( yaxis=opts.AxisOpts( name="GDP增速(%)", type_="value", position="right", axislabel_opts=opts.LabelOpts(formatter="{value}%") ) ) .set_global_opts( title_opts=opts.TitleOpts( title="排放强度与GDP增速", pos_left="center" ), tooltip_opts=opts.TooltipOpts(trigger="axis"), ) ) gdp_line = ( LineOverlay(init_opts=opts.InitOpts( width="520px", height="320px", theme="dark", bg_color="#0b1220" )) .add_xaxis(years) .add_yaxis( "GDP增速", gdp_growth_values, yaxis_index=1, color="#22d3ee", symbol="circle", symbol_size=5, label_opts=opts.LabelOpts(is_show=False) ) ) combo = strength_bar.overlap(gdp_line)逻辑说明:extend_axis在右侧生成第二条 y 轴,但右侧轴默认只挂在 Bar 上,所以 GDP 增速折线要用yaxis_index=1指定走右侧轴。两条数据的量级差很多——排放强度可能在个位数,GDP 增速在个位数百分比——不分开坐标轴的话折线会被压成一条水平线。
参数说明:fillna(0)把第一年的 NaN 补成 0,是因为没有上一年数据就无法算增速,大屏上总不能留个空洞。overlap是 pyecharts 2.x 里把两个 chart 叠加的标准做法,比手写Grid简单,适合这种「一把柱一根线」的组合图。
4.5 把图表拼成大屏并导出固定版式
四张图单独生成没问题,但大屏要的是「一张整页」。pyecharts 官方推荐的拖拽布局能省掉手写 HTML 的麻烦:
page = Page(layout=Page.DraggablePageLayout) page.add(trend_line, pie_chart, bar_chart, combo) page.render("co2_dashboard_render.html")第一步先render生成一个可拖拽页面,用浏览器打开,把四张图拖到你想要的位置。摆好后点页面右上角的「Save Config」,会下载一个chart_config.json。然后在脚本里接着执行:
page.save_resize_html( source="co2_dashboard_render.html", cfg_file="chart_config.json", dest="co2_dashboard.html" )这段代码说明:save_resize_html会把拖拽好的位置、宽高固化到新文件里,之后图表数据变了,只要重新跑build_dashboard.py,布局还是原来调好的样子,不需要再拖一次。拖拽布局第一次用是有点玄学,两个图表会叠在一起,别慌,从右上角抓住标题栏区域拖就行。
提示:拖拽布局适合做「一次性固定版式」。如果后面要频繁改布局,页面中央那套自动缩放脚本会干扰拖拽,建议改好布局后再接分辨率适配。
5. 大屏制作避坑记录:5 个最常翻车的现场
5.1 内网部署白屏:ECharts 的 CDN 资源被拦
现象:本地打开co2_dashboard.html一切正常,拷到内网服务器上,双击变成白屏,控制台报一堆net::ERR_FAILED。
原因:pyecharts 生成的 HTML 默认从 CDN 加载 ECharts 脚本和主题资源。内网环境访问不了外网,图表根本拿不到渲染引擎。
解决:在交付前就把外部资源本地化。用浏览器打开生成的 HTML,搜索src=和href=,把所有指向https://cdn.jsdelivr.net和https://assets.pyecharts.org的链接下载到项目根目录的assets/文件夹,然后把 HTML 里的引用路径改成assets/xxx.js这种相对路径。pyecharts 引用的 JS 不止一个,最稳妥的办法是下载全部后逐个替换,别只替换一个 ECharts 主文件。这个操作做完,内网环境随便拷,永不白屏。
5.2 中文字体和标签乱码
现象:大屏在 Windows 上中文显示正常,部署到国产化终端或某些 Linux 环境的浏览器里,图表的标题和标签变成方块。
原因:图表字体用的默认字体在目标系统不存在,浏览器回退失败。
解决:在所有LabelOpts、TitleOpts里显式指定font_family="Microsoft YaHei",如果目标环境是 Linux,改成"Noto Sans CJK SC"更稳。HTML 的<head>里也要保证有<meta charset="utf-8">,否则读取本地文件时可能按系统默认编码解析,中文直接乱掉。
5.3 大屏在不同分辨率下变形
现象:1920×1080 上正好占满一屏,换到 1366×768 的显示器,右侧图被挤出屏幕,底部出现滚动条。
原因:pyecharts 生成的是固定像素宽高的图表,浏览器窗口变小后没有等比缩放。
解决:给大屏套一个固定 1920×1080 的容器,用 JS 按视口比例缩放,而不是靠 CSS 百分比硬撑。在 HTML 里加:
function scaleDashboard() { const el = document.querySelector('.dashboard-body'); const scaleW = window.innerWidth / 1920; const scaleH = window.innerHeight / 1080; const scale = Math.min(scaleW, scaleH); el.style.transformOrigin = '0 0'; el.style.transform = 'scale(' + scale + ')'; } window.addEventListener('resize', scaleDashboard); scaleDashboard();Math.min保证宽高都不溢出,宁可两侧留一点黑边,也不能出现滚动条。这个脚本要在图表渲染完成后执行,否则 ECharts 拿到的容器尺寸还是缩放前的值。
5.4 数据更新了,图表却还是老数据
现象:第二天跑了一遍脚本,数据库里的值变了,打开大屏还是昨天的数。
原因:浏览器把co2_dashboard.html缓存了,或者你是手动打开的文件,根本没重新生成。
解决:把静态方案的「刷新」做成一条流水线:定时任务每天跑process_data.py重新算数据,再跑build_dashboard.py生成新 HTML。页面本身加一个一小时级的自动重载:
<meta http-equiv="refresh" content="3600">如果你走的是 FastAPI 接口方案,可以在接口里吐最新 JSON,前端用setInterval每 5~10 分钟重新拉一次再setOption。大屏的「实时」多数时候不是秒级需求,别一上来就上 WebSocket。
5.5 趋势外推的“预测”被外行当场质疑
现象:大屏上画了一条延伸到 2027 年的趋势虚线,评审会上业务专家直接问:凭什么说 2026 年就是这个数?你用了什么模型?
原因:线性趋势线天然有外推性质,但年度样本只有十几年,把它当预测展示,容易被当成精确预测来攻击。
解决:趋势线只覆盖有数据的年份范围,不向未来延伸。如果一定要给个方向,把未来两年的趋势部分单独用灰色虚线画出来,并在副标题里写「基于历史趋势外推,不含政策情景」。《强加时间范围的tooltip》也别让两年后的数据点太显眼。汇报的落点是「趋势正在放缓还是加速」,而不是「2027 年具体排多少万吨」。
6. 交付前把大屏当产品验一遍:截屏回归与数据刷新
大屏做完,别急着交付,先当产品测一遍。我最常用的验证方法很简单:用 Headless 浏览器截一张 1920×1080 的图,人工看一遍有没有空白块、遮挡、图例重叠。代码不长:
from selenium import webdriver from selenium.webdriver.chrome.options import Options opts = Options() opts.add_argument("--headless") opts.add_argument("--no-sandbox") opts.add_argument("--force-device-scale-factor=1") driver = webdriver.Chrome(options=opts) driver.set_window_size(1920, 1080) driver.get("file:///D:/projects/co2_dashboard/co2_dashboard.html") driver.save_screenshot("dashboard_check.png") driver.quit()截图只是第一层。我还会在真实浏览器里打开控制台,逐张图移动鼠标,hover 每个数据点。ECharts 的 tooltip 在某些缩放比例下有偏移,这个问题截图测不出来,必须手工过一遍。确认没有 JS 报错、tooltip 位置正常,再拿去投屏。
如果大屏是给领导汇报用的,我还有一个习惯:把所有图表的单位写进副标题里。总量是「万吨 CO2」,强度是「吨 CO2/万元 GDP」,部门占比是「占当年总排放比例」。单位不写清楚,大屏上再漂亮的图表都会被一句「这个数到底什么单位」给问住。我第一次交付碳排大屏时,就是把一个累计值当成了当年值画进趋势图,上线第一天被现场看出数据对不上,之后所有图表的 tooltip 和副标题都强制带口径。这也是我做碳排大屏最重要的一个习惯:先让人信,再让人看。希望这套流程能帮你少走一轮弯路,把 Python、数据和图表真正串成一块能上台面的大屏。
本文还有配套的精品资源,点击获取