3种数据可视化部署方案(附报错急救指南)
适用人群说明
本教程专为以下群体设计:
- 刚接触宝塔面板的网站运维新手(0-3个月经验)
- 需要将服务器日志、API调用、用户活跃度等数据转为可视化折线的站长
- 想用免费方案替代Grafana/AWS CloudWatch的预算敏感型用户
- 已在宝塔面板安装Python/Node环境,但不知如何绘制折线的中级运维
无论你是想监控网站每日UV变化,还是追踪服务器CPU在过去72小时的波动,本文都能提供可立刻复用的代码模板与配置解药。
模拟数据生成,最近24小时每小时的平均请求数
核心原理:折线图的3条技术路径
在宝塔面板中,有3种主流方式生成折线图:
- Python + Flask + Chart.js(推荐新手,便于调试)
- Node.js + ECharts(适合已有Node项目的团队)
- 纯前端HTML + Canvas(无需后端,静态数据测试用)
本文以路径1为核心展开,另两种路径会在「进阶扩展」中给出关键代码差异。
完整操作步骤:从面板登录到折线图诞生
第一步:创建站点与Python环境
登录宝塔面板后,点击左侧「网站」→「添加站点」:
- 域名:留空(或填写本地IP如127.0.0.1:5000)
- 数据库:不创建
- PHP版本:选择「纯静态」或任意PHP版本(仅用作文件托管)
面板截图位置提示:在「网站」列表页右上角「添加站点」按钮,弹出窗口第三项「PHP版本」下拉菜单中选「纯静态」。
站点创建成功后,点击站点名右侧的「设置」→「配置文件」,确认index指令中是否包含index.py(若没有,手动加上,保存)。
第二步:安装Python依赖库
点击面板左侧「软件商店」,搜索「项目管理器」(若未安装则立即安装),打开项目管理器,选择你的站点根目录(默认为/www/wwwroot/你的站点名):
- Python版本:选3.8或3.9(宝塔预装Python3.7+,建议升级)
- 框架:选Flask
- 安装方式:勾选「自动安装依赖」
等待项目初始化后,点击「终端」按钮,在项目管理器终端命令行输入以下命令:
pip install flask matplotlib numpy
注意:matplotlib是后端绘图库,会导致页面加载延迟(约0.5-1秒),若追求实时性可改用Chart.js前端渲染,后文会提供替代方案。
第三步:编写核心代码文件
在站点根目录创建两个文件:
文件1:app.py(后端数据接口)
from flask import Flask, render_template, jsonify
import random
import time
app = Flask(__name__)
def generate_daily_data():
now = time.time()
hours = []
values = []
for i in range(23, -1, -1):
timestamp = now - i * 3600
# 转换成本地时间,只取小时
hour_str = time.strftime("%H:00", time.localtime(timestamp))
hours.append(hour_str)
# 模拟正态分布数据,中心在12时有高峰
base = 100 * (1 - abs(i - 12) / 24) + random.randint(-10, 30)
base = max(10, int(base))
values.append(base)
return {"hours": hours, "values": values}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/data')
def get_data():
data = generate_daily_data()
# 模拟有时数据为空(万一接口出错,页面仍能显示)
if random.random() < 0.1:
return jsonify({"error": "数据源暂不可用"}), 503
return jsonify(data)
if __name__ == '__main__':
# 必须监听0.0.0.0,否则外网无法访问
app.run(host='0.0.0.0', port=5000, debug=False)
文件2:templates/index.html(前端折线页面)
在站点根目录创建templates文件夹,放入以下代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">宝塔折线监控</title>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
body { background: #f0f2f5; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
.chart-container { width: 800px; max-width: 95%; background: white; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); padding: 20px; }
canvas { max-height: 400px; }
.error-message { color: #e74c3c; text-align: center; display: none; margin-top: 20px; }
</style>
</head>
<body>
<div class="chart-container">
<h2 style="text-align:center; margin-bottom: 20px; font-weight: 400;">网站请求监控(最近24小时)</h2>
<canvas id="myChart"></canvas>
<div class="error-message" id="errorMsg">⚠️ 数据加载失败,5秒后自动重试...</div>
</div>
<script>
async function loadChart() {
const ctx = document.getElementById('myChart').getContext('2d');
document.getElementById('errorMsg').style.display = 'none';
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error('HTTP状态码: ' + response.status);
const data = await response.json();
if (data.error) {
throw new Error(data.error);
}
// 如果已有图表实例,先销毁再创建
if (window.myChartInstance) {
window.myChartInstance.destroy();
}
window.myChartInstance = new Chart(ctx, {
type: 'line',
data: {
labels: data.hours,
datasets: [{
label: '请求数',
data: data.values,
borderColor: '#3498db',
backgroundColor: 'rgba(52, 152, 219, 0.1)',
fill: true,
tension: 0.3,
pointRadius: 4,
pointHoverRadius: 6
}]
},
options: {
responsive: true,
plugins: {
legend: { display: true, position: 'top' }
},
scales: {
y: { beginAtZero: true, title: { display: true, text: '请求数' } },
x: { title: { display: true, text: '时间' } }
}
}
});
} catch (error) {
console.error('图表加载错误:', error);
document.getElementById('errorMsg').style.display = 'block';
// 5秒后重试
setTimeout(loadChart, 5000);
}
}
// 首次加载
loadChart();
// 每30秒自动刷新数据
setInterval(loadChart, 30000);
</script>
</body>
</html>
第四步:启动服务并设置守护
回到「项目管理器」,在项目列表中找到你的项目,点击「启动」按钮,若显示「运行中」,则服务已启动。
面板截图位置提示:在「项目管理器」的「项目列表」标签页,每行右侧有「启动/停止/重启」按钮,绿色图标表示运行中。
关键配置参数:
host='0.0.0.0':必须为0.0.0.0,默认127.0.0.1只能本机访问port=5000:可改为其他端口如8080,但需在宝塔「安全」菜单放行该端口debug=False:生产环境必须关闭debug,否则占用额外进程
第五步:访问验证
在浏览器地址栏输入:http://你的服务器IP:5000(若用域名需先解析),你应该看到一条平滑的蓝色折线,随时间变化上下波动,鼠标悬停在数据点上,会显示具体数值。
常见报错解决(新手必看)
报错1:Flask项目启动后,浏览器访问显示“无法访问此网站”
- 原因:服务器防火墙未放行端口,或监听地址未设置为0.0.0.0
- 解决:①宝塔面板→「安全」→「添加端口规则」,输入5000,协议TCP;②检查
app.py中run(host='0.0.0.0', port=5000)的host是否为0.0.0.0
报错2:页面加载后显示“数据加载失败,5秒后自动重试...”且一直循环
- 原因:
/api/data接口返回了HTTP 503或非JSON数据 - 解决:逐个排查——打开浏览器调试工具(F12→网络/Network),刷新页面,查看
api/data的响应状态码:- 404:检查Flask路由是否写错,确保
@app.route('/api/data')与fetch('/api/data')完全一致,注意大小写 - 500:查看项目管理器终端中的红色报错信息,最常见的是
random模块未导入——在终端运行pip install random(Python标准库通常自带,但某些精简版环境可能缺失) - 503:是代码中故意模拟的随机错误,刷新页面即可恢复
- 404:检查Flask路由是否写错,确保
报错3:折线图显示为空白,但数据已成功加载
- 原因:前端Canvas绘制时,
labels和data长度不一致或包含空值 - 解决:在
app.py中给generate_daily_data()函数增加返回值长度检查:assert len(hours) == 24 and len(values) == 24, "数据长度必须为24"
若仍报错,将前端
new Chart(ctx, {...})中的data.hours改为data.hours.slice(0, 24)做截断保护。
报错4:站点访问非常慢(加载超过5秒)
- 原因:Chart.js CDN国内访问不稳定
- 解决:将
index.html中的CDN链接替换为本地文件:去百度搜索「ECharts CDN 最新」,或直接保存Chart.js文件到站点根目录的static文件夹,修改script标签的src为/static/chart.umd.min.js
进阶扩展:换用ECharts或纯前端
Node.js + ECharts 路径差异:
- 使用
npm install echarts,而非CDN - 后端用
http.createServer代替Flask - 数据格式默认支持JSON,需额外实现定时生成
纯前端HTML + Canvas路径(无需后端):
- 在
templates/index.html中直接用<script>模拟数据:const data = generateMockData() - 适合只有一次部署、不涉及实时更新的场景
- 无需启动任何服务,直接双击打开HTML文件即可
最后的叮嘱
完成上述步骤后,恭喜你,你已经拥有一个能自我更新的网站监控折线图了!如果出现任何卡顿,第一件事是查看项目管理器的终端日志——红色高亮的文本就是故障答案,只要保持pip包安装完整、端口放行正确、Flask路由路径一致,这条折线就会像你的网站心跳一样稳定跳动。



发表评论