目录
1.1. 项目介绍
今天我们介绍一个从数据采集、数据加工、数据预测,最后集成到数据可视化展示的一个完整的项目案例。
1.2. 技术栈
- 前端:Vue.js
- 后端:Flask
- 数据源:全国空气质量监测数据(可从公开API获取)
- 可视化库:Echart.js
1.3. 数据来源
通过实时采集全国 23个省、5个自治区、4个直辖市和2个特别行政区下的293个市的每一天的空气质量数据。
通过分析网站接口,扣取JS代码,编写后端代码嗲用js,实现数据的采集。
1.3.1. 设置城市和时间为爬虫程序的入口
m0fhOhhGL = "GETDAYDATA"
oNLhNQ = {
city: '云浮',
month: '202309'
}
1.3.2. 爬虫程序主要代码
function poPBVxzNuafY8Yu (m0fhOhhGL, oNLhNQ) {
var aMFs = "3c9208efcfb2f5b843eec8d96de6d48a";
var cVWG2 = "WEB";
var t5GECZQ = new Date().getTime();
var pKmSFk8 = {
appId: aMFs,
method: m0fhOhhGL,
timestamp: t5GECZQ,
clienttype: cVWG2,
object: oNLhNQ,
secret: hex_md5(aMFs + m0fhOhhGL + t5GECZQ + cVWG2 + JSON.stringify(osZ34YC04S(oNLhNQ)))
};
pKmSFk8 = BASE64.encrypt(JSON.stringify(pKmSFk8));
pKmSFk8 = AES.encrypt(pKmSFk8, acky6QolJSJi, acixHVhiNqmK);
return pKmSFk8;
}
function dxvERkeEvHbS(data) {
data = BASE64.decrypt(data);
data = DES.decrypt(data, dskQCqpdBOGo, dsiqYiQHbZQp);
data = AES.decrypt(data, ask4u6FbhGV8, asi2hhkBUJbo);
data = BASE64.decrypt(data);
return data;
}
1.3.3. 后端代码调用js
# -*- coding: utf-8 -*-
"""
@Time : 2024/8/30 22:10
@Auth : Gmq
@File :xxx.py
@IDE :PyCharm
@WECHAT :debugger66
"""
import json
import time
from queue import Queue
import requests
import execjs
from pymongo import MongoClient
from lxml import etree
client = MongoClient()
collection = client['2tData']['airquality']
class GN:
def __init__(self):
self.url = 'https://www.aqistudy.cn/historydata/api/historyapi.php'
self.headers = {
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.9,zh-CN;q=0.8,zh;q=0.7",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Origin": "https://www.aqistudy.cn",
"Sec-Fetch-Site": "none",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
"sec-ch-ua": "Not/A)Brand;v=8, Chromium;v=126, Microsoft Edge;v=126",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "Windows",
"Referer": "https://www.aqistudy.cn/historydata/daydata.php?city=^%^E5^%^8C^%^97^%^E4^%^BA^%^AC&month=2023-11^",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
}
self.m0fhOhhGL = 'GETDAYDATA'
self.oNLhNQ = {}
self.js = execjs.compile(open('xxx.js',encoding='utf-8').read())
# self.ip_queue = Queue()
def request_data(self, city, month):
self.oNLhNQ['city'] = city
self.oNLhNQ['month'] = month
proxy_ip = self.ip_queue.get()
# 使用代理必须设置代理账号和密码
username = '代理账号'
password = '代理密码'
proxies = {
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
}
pKmSFk8 = self.js.call('poPBVxzNuafY8Yu', self.m0fhOhhGL, self.oNLhNQ)
print(pKmSFk8)
res = requests.post(self.url, headers=self.headers, data={'hA4Nse2cT': pKmSFk8})
result = self.js.call('dxvERkeEvHbS', res.text)
return json.loads(result)
def run(self):
for one_city in self.get_city():
reuslt = self.request_data(one_city, '202405')
for i in reuslt['result']['data']['items']:
i['city'] = one_city
collection.insert_one(i)
@staticmethod
def get_city():
citys = []
with open('./a.html', 'r', encoding='utf-8') as f:
text = f.read()
xhtml = etree.HTML(text)
lis = xhtml.xpath('//div[@class="all"]//ul[@class="unstyled"]/div/li')
for li in lis:
city = li.xpath('./a/text()')
citys.append(city[0])
return citys
if __name__ == '__main__':
gn = GN()
gn.run()
1.4. 后端实现
1.4.1 介绍
后端采用flask框架编写数据接口和主要逻辑处理,采用mysql数据库进行数据的增删改查。
1.4.2 项目架构
flask_project/
│
├── app/ # 主应用目录
│ ├── __init__.py # 应用工厂模式
│ ├── routes.py # 路由定义
│ ├── models.py # 数据模型
│ ├── forms.py # 表单定义
│ ├── static/ # 静态文件(CSS、JavaScript、图片)
│ ├── templates/ # 模板文件(HTML)
│ ├── config.py # 配置文件
│ └── extensions.py # 扩展初始化
│
├── migrations/ # 数据库迁移文件
│
├── tests/ # 测试代码
│ └── ... # 测试用例
│
├── .env # 环境变量配置
├── .gitignore # Git 忽略文件
├── requirements.txt # 项目依赖
├── run.py # 启动脚本
└── README.md # 项目说明文件
1.5. 前端实现
1.5.1 介绍
前端使用Vue 进行数据的交互和响应,可根据需求扩展功能,比如添加更多的 API、使用 Vuex 管理状态、添加路由等。通过前后端分离的方式,能够提高应用的可维护性和扩展性。
my-project/
│
├── backend/ # Flask 后端代码
│ ├── app.py # Flask 主应用文件
│ ├── requirements.txt # 后端依赖
│ └── ... # 其他后端文件
│
├── frontend/ # Vue 前端代码
│ ├── src/
│ │ ├── components/ # Vue 组件
│ │ ├── views/ # 页面视图
│ │ ├── router/ # 路由配置
│ │ ├── store/ # Vuex 状态管理
│ │ ├── App.vue # 根组件
│ │ └── main.js # 入口文件
│ ├── public/
│ └── package.json # 前端依赖
│
└── README.md # 项目说明文件
1.6. 页面展示
1.6.1. 地图展示
地图展示主要通过地图向下钻取,选择城市来联动哥哥城市的指标统计数据。
1.6.1.1 省级地图
点击省级区域钻取该省的各个市
1.6.1.2 县级地图
点击市级区域向下钻取到县级
1.6.2. 全国分布
选择不同哥哥空气空气质量指标来展示各个城市的空气质量。
1.6.3. 区域分布
1.6.4. 城市比较
选择不同的城市、指标、月份来比较这两个城市之间的空气质量。
1.6.5. 统计排名
选择城市和月份展示该月份的城市排名和省会排名
1.6.6 历史数据
选择城市展示每个城市的历史数据并且可以按需下载。
1.6.7 模型预测
选择城市预测该城市的AQI