基于Python Flask的全国气象数据采集及可视化系统
- 一、项目简介
 - 二、项目技术
 - 三、项目功能
 - 四、运行截图
 - 五、分类说明
 - 六、实现代码
 - 七、数据库结构
 - 八、源码下载地址
 
一、项目简介
本项目是一个基于Web技术的实时气象数据可视化系统。通过爬取中国天气网的各个城市气象数据,并将其保存到自己的数据库中,我们利用Python、Flask、ECharts和MySQL等技术,实现了数据的分析和可视化呈现。这是一个采用B/S架构的现代化气象数据管理系统,用户只需通过浏览器便可访问。在项目完善版本中,我们进一步优化了数据处理和可视化,提高了系统的性能和用户体验。
二、项目技术
- Python爬虫技术:借助Python强大的网络爬虫库,我们能够高效地从中国天气网上获取实时气象数据,并将其转化为结构化数据。
 - Flask后端框架:作为一种轻量级的后端框架,Flask简化了开发流程,使得我们能够快速搭建灵活且可扩展的Web应用程序。
 - MySQL数据库:作为一个成熟的关系型数据库管理系统,MySQL提供了高效可靠的数据存储和查询能力,使得我们能够方便地管理爬取的气象数据。
 - ECharts大数据可视化:ECharts作为当时流行的数据可视化库,为我们提供了丰富的图表类型和交互式特性,使得我们能够将庞大的气象数据以直观的图表形式展示给用户。
 - layui后台管理前端框架:借助layui框架,我们实现了美观、简洁的后台管理界面,提升了用户操作的友好性和便捷性。
 
三、项目功能
系统功能模块的设计是基于对现实需求的深入理解和用户体验的关注,详情功能结构图,如下图所示。主要包括以下五大功能:
- 可视化功能模块:通过ECharts技术,将爬取的气象数据转化为图表形式,以直观的方式展示各城市的气象情况,使用户能够快速把握气象趋势和变化,更好地做出决策。
 - 版本管理功能模块:用于记录系统的不同版本,包括功能更新、性能优化和Bug修复等内容,确保系统持续发展和不断完善。
 - 用户管理功能模块:实现用户注册、登录和权限控制,不同用户拥有不同的菜单权限,保障系统的安全性和数据隐私。
 - 实时气象数据管理功能模块:用于存储、更新和管理从中国天气网爬取的实时气象数据,确保数据的准确性和及时性。
 - 爬虫管理功能模块:针对爬虫任务进行管理,包括设置爬取频率、指定目标城市等,以确保爬虫的高效稳定运行。

 
四、运行截图
大屏可视化页面
用户登录页面
 
用户注册页面
 
后台管理首页面
 
后台用户管理页面
 
后台版本管理页面
 
后台气象管理页面
 
后台气象编辑页面
 
后台爬虫日志管理页面
 
五、分类说明
AQI:
0-50良好
51-100:中等
101-150:偏差,对敏感人群不健康
151-200:差,不健康
201-300:极差,非常不健康
300+:有毒
风力等级:

六、实现代码
爬虫头部实现代码
class GetWeather:
    def __init__(self):
        self.baseUrl = r""
        self.headers = {'Accept': "*/*",
                        'Accept-Encoding': 'gzip, deflate',
                        'Accept-Language': 'keep-alive',
                        'Connection': '',
                        'Cookie': ''.encode("utf-8").decode("latin1"),
                        'Host': 'd1.weather.com.cn',
                        'Referer': '',
                        'User-Agent': '', }
        self.loadList = []
        # 格式为:列表里面的子列表都是一个省份的所有城市,子列表里所有元素都是字典,每个字典有两项
        self.cityList = [] 
        self.cityDict = {}
        self.result = xlwt.Workbook(encoding='utf-8', style_compression=0)
        self.sheet = self.result.add_sheet('result', cell_overwrite_ok=True)
        self.cityRow = 0
        self.totalGet = 0
 
数据清洗存入数据库
 data = json.loads(self.htmlResult.replace("var dataSK=", ""))
                nameen = data["nameen"]  # 城市拼音
                cityname = data["cityname"]  # 城市名称
                temp = data["temp"]  # 当前温度
                WD = data["WD"]  # 风向
                WS = data["WS"].replace("级", "")  # 风力
                wse = data["wse"].replace("km/h", "")  # 风速
                sd = data["sd"].replace("%", "")  # 湿度
                weather = data["weather"]  # 天气
                record_date = data["date"]  # 时间
                record_time = data["time"]  # 时分
                aqi = data["aqi"]  # 时分
                judge_sql = "select count(id) from `weather` where nameen = '" + nameen + "' and cityname='" + cityname + "' and record_date='" + record_date + "' and record_time='" + record_time + "'";
                sql = "INSERT INTO `weather` VALUES (null, '" + nameen + "', '" + cityname + "', '" + record_date + "', '" + record_time + "', " + str(
                    temp) + ", '" + WD + "', " + WS + ", " + wse + ", " + sd + ", '" + weather + "', " + aqi + ", '" + time.strftime(
                    "%Y-%m-%d %H:%M:%S", time.localtime()) + "',0);"
                i = db.query_noargs(judge_sql)[0][0]
                if int(i) > 0:
                    print("跳过:", judge_sql)
                    continue
                update_sql = "update `weather` set is_old=1 where nameen = '" + nameen + "' and cityname='" + cityname + "'";
                print("插入:", sql)
                count += 1
                db.query_noargs(update_sql)
                db.query_noargs(sql)
 
首页城市空气质量统计
# 获取城市空气质量统计
def get_AQI_total_data():
    db = dbUtil()
    lh_sql = "SELECT COUNT(id) FROM weather WHERE aqi<=50 AND is_old=0"
    zd_sql = "SELECT COUNT(id) FROM weather WHERE aqi>50 AND aqi<=100 AND is_old=0"
    pc_sql = "SELECT COUNT(id) FROM weather WHERE aqi>100 AND aqi<=150 AND is_old=0"
    c_sql = "SELECT COUNT(id) FROM weather WHERE aqi>150 AND aqi<=200 AND is_old=0"
    jc_sql = "SELECT COUNT(id) FROM weather WHERE aqi>200 AND aqi<=300 AND is_old=0"
    yd_sql = "SELECT COUNT(id) FROM weather WHERE aqi>300 AND is_old=0"
    lh = db.query_noargs(lh_sql)[0][0]
    zd = db.query_noargs(zd_sql)[0][0]
    pc = db.query_noargs(pc_sql)[0][0]
    c = db.query_noargs(c_sql)[0][0]
    jc = db.query_noargs(jc_sql)[0][0]
    yd = db.query_noargs(yd_sql)[0][0]
    db.close_commit()
    return jsonify([{"time": "良好", "value": lh, "name": "空气质量"},
                    {"time": "中等", "value": zd, "name": "空气质量"},
                    {"time": "偏差", "value": pc, "name": "空气质量"},
                    {"time": "较差", "value": c, "name": "空气质量"},
                    {"time": "极差", "value": jc, "name": "空气质量"},
                    {"time": "有毒", "value": yd, "name": "空气质量"}])
 
空气质量可视化构建
function center_kqzlfm() {    
    $.ajax({       
        url: "/main/aqi",
        method: "get",
        success: function (obj) {
            // 基于准备好的dom,初始化echarts实例            
            const myChart = echarts.init(document.getElementById("kqzlfm-table")) 
            // 指定图表的配置项
            let option = {...}            
            // 指定图表的数据
            let data = obj            
            //数据处理 开始
            let xKey = "time" 
            let yKey = "value" 
            let sKey = "name"
            let seriesArr = []
            let dataColumn = []   
            //....省略数据格式化处理太长了
            option.yAxis.type = "value"
            option.xAxis.type = "category"
            option.xAxis.data = dataColumn
            // 数据处理完 
            option.series = seriesObj
            // 使用刚指定的配置项和数据显示图表。
            myChart.setOption(option) 
        }   
    })}
 
七、数据库结构
slog表
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| id | int | 是 | |
| log | varchar(255) | 否 | |
| create_time | datetime | 否 | 
sys_version表
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| id | int | 是 | 系统版本 | 
| sys_name | varchar(255) | 否 | 名称 | 
| sys_version | varchar(255) | 否 | 描述 | 
user表
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| id | int | 是 | |
| name | varchar(255) | 否 | 用户名称(供应商名称) | 
| account | varchar(255) | 否 | 用户账号 | 
| password | varchar(255) | 否 | 用户密码 | 
| company | varchar(255) | 否 | 企业名称 | 
| phone | varchar(255) | 否 | 电话号码 | 
| varchar(255) | 否 | 邮箱 | |
| type | int | 否 | 0管理员,1普通用户 | 
| status | int | 否 | 0禁用1启用 | 
weather表
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| id | int | 是 | |
| nameen | varchar(255) | 否 | 城市拼音 | 
| cityname | varchar(50) | 否 | 城市名称 | 
| record_date | varchar(50) | 否 | 天气时间 | 
| record_time | varchar(50) | 否 | 实时时分 | 
| temp | int | 否 | 当前温度 | 
| wd | varchar(20) | 否 | 风向 | 
| ws | int | 否 | 凤力 | 
| wse | int | 否 | 风速 | 
| sd | int | 否 | 湿度 | 
| weather | varchar(20) | 否 | 天气 | 
| aqi | int | 否 | 空气质量 | 
| create_time | datetime | 是 | 数据创建时间 | 
| is_old | int | 否 | 1老数据,0新数据 | 
八、源码下载地址
原创项目,开发不易,保证项目经过多人调试与测试,可以准确无误运行(经过最新调试,系统依旧可以持续运行)
项目获取地址:
#浏览器打开一下官方网站进行项目源码下载
www.shiyuncode.com/productlist/2?search=%E6%B0%94%E8%B1%A1
                

















