🎈 博主:一只程序猿子
🎈 博客主页:一只程序猿子 博客主页
🎈 个人介绍:爱好(bushi)编程!
🎈 创作不易:喜欢的话麻烦您点个👍和⭐!
🎈 除此之外您还可以通过个人名片联系我
目录
1.介绍
在上篇文章中,我们已经成功利用Python爬虫技术从中药材天地网捕获了丰富的中药材市场价格数据,包括几种关键中药材的历史价格变动信息。经过精心的数据清洗和整理后,这些宝贵的数据被妥善地存储到了MySQL数据库中,为后续的分析与可视化工作奠定了坚实的基础。在本篇文章中,我们将借助Flask框架构建后端服务,并结合Echarts的强大可视化功能,对这些数据进行深入分析,并以直观、生动的图表形式进行展示,从而帮助读者更好地理解中药材市场的价格变动趋势和规律。
2.技术选型
(1)Flask
Flask是一个轻量级的Web应用框架,它设计简单且易于扩展,非常适合快速构建Web应用。Flask的特点在于其灵活性和可扩展性,它不会强制用户使用特定的库或工具,而是提供了足够的自由度让开发者根据自己的需求来选择最适合的组件。此外,Flask拥有庞大的社区支持和丰富的文档资源,使得开发者在遇到问题时能够迅速找到解决方案。
选择Flask作为后端框架的原因主要有以下几点:首先,Flask的轻量级特性使得项目可以快速启动和部署,降低了开发成本。其次,Flask的灵活性使得我们可以根据项目需求自由定制功能,而不会被框架本身所限制。最后,Flask的社区支持和文档资源为我们在开发过程中提供了强大的后盾。
(2)Echarts
Echarts是一个使用JavaScript实现的开源可视化库,它提供了直观、生动且交互性强的数据可视化图表。Echarts拥有丰富的图表类型,如折线图、柱状图、饼图等,能够满足各种数据可视化需求。此外,Echarts还支持丰富的配置项,允许用户根据自己的需求定制图表的样式和行为。
选择Echarts作为前端可视化工具的原因主要有以下几点:首先,Echarts的图表类型丰富,能够直观地展示中药材价格数据的各种特征。其次,Echarts的交互性强,用户可以通过鼠标悬停、点击等操作与图表进行互动,获取更多信息。最后,Echarts的开源特性使得我们可以免费使用并对其进行定制,以满足项目的特定需求。
综上所述,Flask和Echarts分别在后端框架和前端可视化工具方面具有显著的优势,它们的结合使得我们能够高效地构建出功能强大且界面美观的中药材价格分析与可视化平台。
3.数据收集
在上一篇文章中我们已经完成了数据收集:
4.项目结构
5.项目开发
(1)后端开发(Flask)
app.py(部分):
import json
from flask_cors import *
from flask import Flask, render_template, Response
from DBhelper import DBHelper
from SQLdesign import *
# 创建一个 Flask web 应用实例,命名为 app。
app = Flask(__name__)
# 如果需要前后端分离或者在其他地方使用异步请求的时,需要加上这一行,解决跨域问题。
CORS(app, supports_credentials=True)
# 使用 app.route() 装饰器来定义一个路由。
# 当用户访问应用的根 URL('/')时,会调用下面的 index() 函数。
@app.route('/')
# 定义一个名为 index 的函数,它返回一个响应。
def index():
# 使用 render_template 函数来渲染一个名为 'index.html' 的模板文件,
# 并将其作为响应返回给客户端。这通常是一个 HTML 文件,用于显示网页内容。
return render_template('index.html')
'''市场价格Top20'''
# 使用 Flask 的 app.route() 装饰器定义一个新的路由,当用户访问 '/priceTop20' URL 时,将执行下面的 priceTop20() 函数。
@app.route('/priceTop20')
# 定义一个名为 priceTop20 的函数,它用于处理 '/priceTop20' 路由的请求。
def priceTop20():
# 创建一个 DBHelper 类的实例,并调用其 select_db 方法来从数据库中选取价格前20名的数据。
# SelectPrice_top20 是一个用于查询的 SQL 语句。
data = DBHelper().select_db(SelectPrice_top20)
# 初始化两个空列表,用于存储从数据库中获取的商品名称和最近价格。
names = []
recentprices = []
# 初始化一个空字典,用于存储结果。
results = {}
# 遍历从数据库中获取的数据。
for i in data:
# 将每条数据的 'name' 字段添加到 names 列表中。
names.append(i['name'])
# 将每条数据的 'recentprice' 字段添加到 recentprices 列表中。
recentprices.append(i['recentprice'])
# 将 names 列表添加到 results 字典的 'names' 键中。
results['names'] = names
# 将 recentprices 列表添加到 results 字典的 'recentprices' 键中。
results['recentprices'] = recentprices
# 使用 Flask 的 Response 对象来创建一个 JSON 格式的响应。
# 使用 json.dumps() 将 results 字典转换为 JSON 格式的字符串。
# 设置响应的 mimetype 为 'application/json',表示返回的是 JSON 数据。
return Response(json.dumps(results), mimetype='application/json')
(2)前端开发(Echarts)
index.html:
<!DOCTYPE html>
<html style="height: 100%;width:100%">
<head>
<meta charset="utf-8">
<title>中药材价格可视化大屏</title>
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
<div class="container">
<div id="title">中药材价格可视化大屏</div>
<div id="top"></div>
<div class="bottom-container">
<div class="bottom-container-left">
<div class="select">
<select id="select_1">
<option value="1" class="active">白术</option>
<option value="2">麦冬</option>
<option value="3">川芎</option>
<option value="4">白芍</option>
</select></div>
<div id="left"></div>
</div>
<div class="bottom-container-right">
<div class="select">
<select id="select_2">
<option value="1" class="active">年涨幅</option>
<option value="2">月涨幅</option>
<option value="3">周涨幅</option>
</select></div>
<div id="right"></div>
</div>
</div>
</div>
<script type="text/javascript" src="/static/js/echarts.min.js"></script>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="/static/js/top.js"></script>
<script type="text/javascript" src="/static/js/left.js"></script>
<script type="text/javascript" src="/static/js/right.js"></script>
</body>
</html>
top.js:
$.ajax({
type: 'GET',
url: "http://127.0.0.1:5000/priceTop20",
dataType: 'json',
success: function(data) {
console.log(data);
//html原本的js代码
var dom = document.getElementById("top");
var myChart = echarts.init(dom);
var option;
// var app ={};
option = {
title: {
text: '市场价格Top20', // 标题文本内容
// left: 'center', // 标题的水平位置,可选值包括 'left'、'center'、'right' 或者具体的像素值
textStyle: { // 标题文本的样式
color: '#333', // 字体颜色
fontWeight: 'bold', // 字体粗细
fontSize: 20 // 字体大小
}
},
tooltip: {
show: true
},
grid: {
left: 30,
top: 30,
bottom: 20,
right: 70,
containLabel: true
},
xAxis: {
type: 'value',
name: '元/Kg',
boundaryGap: false,
max: data["recentprices"][0] + 500, // Math.ceil(max / 4) * 5 || 10
axisLine: {
show: true,
lineStyle: {
color: '#c78686'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#2d2d2d'
},
splitLine: {
lineStyle: {
color: ['#CEEDFF'],
type: [5, 8],
dashOffset: 3
}
},
},
yAxis: {
type: 'category',
data: data["names"],
name: "药材名称",
axisLine: {
show: true,
lineStyle: {
color: '#c78686'
}
},
axisTick: {
length: 3
},
axisLabel: {
fontSize: 14,
color: '#666',
margin: 16,
padding: 0
},
inverse: true,
},
series: [{
type: 'bar',
showBackground: true,
backgroundStyle: {
color: 'rgba(82, 168, 255, 0.1)',
borderRadius: [0, 8, 8, 0]
},
itemStyle: {
color: '#52A8FF',
normal: {
borderRadius: [0, 8, 8, 0],
color: function(params) {
// 定义一个颜色集合
let colorList = [
'#52A8FF',
'#00B389',
'#FFA940',
'#FF5A57',
'#29EFC4',
'#F8AEA4',
'#FFC53D',
'#009982',
'#C099FC',
'#F5855F',
'#52A8FF',
'#00B389',
'#FFA940',
'#FF5A57',
'#29EFC4',
'#F8AEA4',
'#FFC53D',
'#009982',
'#C099FC',
'#F5855F',
];
// 对每个bar显示一种颜色
return colorList[params.dataIndex];
},
},
},
barMaxWidth: 16,
label: {
show: true,
position: 'right',
offset: [-5, 2],
color: '#65de67'
},
data: data["recentprices"],
}, ],
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
// 监听窗口的resize事件
window.addEventListener('resize', function() {
myChart.resize(); // 调用图表的resize方法
});
}
});
jquery-3.5.1.min.js和echarts.min.js很容易从网上下载到。
注意:由于篇幅有限,并未在此给出完整源码,完整源码可通过文章底部个人名片获取!
6.项目运行与展示
(1)运行项目
(2)接口展示
/priceTop20:
/fluctuationTop10:
/historicalprice: