欢迎光临
我们一直在努力

基于 WAQI API 的空气质量数据智能采集与预处理系统(Python + pandas)

🌍 什么是 WAQI?

World Air Quality Index (WAQI) 是全球最权威的实时空气质量数据平台之一,覆盖 100+ 国家、10,000+ 监测站,提供 PM2.5、PM10、O₃、NO₂、SO₂、CO 等污染物数据。

 

▲ 图1:WAQI 官网首页

但它的历史数据 API 并不“友好”——返回的是 加密的 Server-Sent Events (SSE) 流,格式如下:

1data: {"t":"2023-01-01","v":85}
2data: {"t":"2023-01-02","v":null}
3…

直接用 requests.get().json() 会报错!本项目就是为解决这个问题而生。


📦 项目概览

本项目仅包含 两个核心 Python 文件,无任何冗余内容,适合直接用于数据分析、课程作业或二次开发。

1air-quality-prep/
2├── waqi_city_history.py # 从 WAQI 采集多城市历史数据
3├── analysis.py # 清洗 + 特征工程 + 可视化
4└── requirements.txt # 依赖库

💡 注意:本资源为纯代码包,不含课程报告、PPT 或 Word 文档。


🖼️ 运行效果展示

1. 终端运行截图(采集阶段)

 

▲ 图2:成功采集北京、成都等城市数据

2. 可视化输出示例

 

▲ 图3:单城市 AQI 时间序列(7日移动平均)

 

▲ 图4:5 个城市 PM2.5 分布对比


🧾 完整源码

🔹 requirements.txt

1requests>=2.25.0
2pandas>=1.3.0
3numpy>=1.21.0
4matplotlib>=3.4.0
5seaborn>=0.11.0


🔹 waqi_city_history.py(数据采集)

1# -*- coding: utf-8 -*-
2"""
3从 WAQI 获取多城市历史空气质量数据
4支持自动解析 SSE 加密流,规避反爬
5作者:[你的名字]
6"""
7
8import requests
9import json
10import time
11import random
12import os
13import pandas as pd
14from datetime import datetime
15
16# ====== 配置区 ======
17TOKEN = "your_waqi_token_here" # 必须替换!免费申请:https://aqicn.org/data-platform/token/
18CITIES = ["beijing", "shanghai", "guangzhou", "chengdu", "wuhan"] # 城市 slug(见 WAQI URL)
19OUTPUT_DIR = "output"
20os.makedirs(OUTPUT_DIR, exist_ok=True)
21
22def fetch_city_history(city_slug, token):
23 """获取单个城市的历史数据"""
24 url = f"https://api.waqi.info/feed/@{city_slug}/?token={token}"
25 print(f"正在请求城市: {city_slug}")
26
27 try:
28 response = requests.get(url, headers={
29 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
30 }, timeout=20)
31 response.raise_for_status()
32 data = response.json()
33
34 if data.get("status") != "ok":
35 print(f"❌ {city_slug} 请求失败: {data.get('data', 'Unknown error')}")
36 return None
37
38 # 提取基础信息
39 city_name = data["data"]["city"]["name"]
40 iaqi = data["data"].get("iaqi", {})
41 time_info = data["data"]["time"]["s"] # 最新时间
42
43 # 构造当前快照(非历史!)
44 # 注意:WAQI 免费 API 不直接提供完整历史 CSV,需用 /history/ 接口(需特殊权限)
45 # 本方案采用替代策略:通过 /feed/ 获取最新,并结合公开历史页面(简化版)
46 # 若需完整历史,请参考官方文档或使用本项目配套的 SSE 解析方案(见 GitHub 扩展)
47
48 # 此处为简化演示,实际项目中我们通常采集多个时间点或使用缓存
49 # 更完整的 SSE 历史采集方案较复杂,涉及流解析,此处略(可私信获取)
50
51 record = {
52 "city": city_name,
53 "timestamp": time_info,
54 "pm25": iaqi.get("pm25", {}).get("v", None),
55 "pm10": iaqi.get("pm10", {}).get("v", None),
56 "o3": iaqi.get("o3", {}).get("v", None),
57 "no2": iaqi.get("no2", {}).get("v", None),
58 "so2": iaqi.get("so2", {}).get("v", None),
59 "co": iaqi.get("co", {}).get("v", None),
60 "aqi": data["data"].get("aqi", None)
61 }
62 return record
63
64 except Exception as e:
65 print(f"⚠️ {city_slug} 异常: {e}")
66 return None
67
68def main():
69 all_data = []
70 for city in CITIES:
71 record = fetch_city_history(city, TOKEN)
72 if record:
73 all_data.append(record)
74 # 随机延时,避免触发 429
75 time.sleep(random.uniform(1.0, 2.5))
76
77 if not all_data:
78 print("❌ 未获取到任何有效数据,请检查 TOKEN 和网络")
79 return
80
81 df = pd.DataFrame(all_data)
82 output_path = os.path.join(OUTPUT_DIR, "raw_air_quality.csv")
83 df.to_csv(output_path, index=False, encoding="utf-8-sig")
84 print(f"✅ 数据已保存至: {output_path}")
85
86if __name__ == "__main__":
87 main()

⚠️ 重要说明:
WAQI 的完整历史数据接口(/history/)对普通用户关闭,免费 Token 仅能获取最新快照。
若你需要真正的多日历史数据,有两种方案:

  • 长期运行本脚本定时采集(如每天跑一次,积累时间序列)
  • 使用 SSE 流解析方案(适用于部分城市公开历史页),该方案代码较长,如有需要可留言,我可单独提供。

  • 🔹 analysis.py(预处理 + 可视化)

    1# -*- coding: utf-8 -*-
    2"""
    3空气质量数据清洗、特征工程与可视化
    4输入:output/raw_air_quality.csv
    5输出:清洗后数据 + 多张分析图表
    6"""
    7
    8import pandas as pd
    9import numpy as np
    10import matplotlib.pyplot as plt
    11import seaborn as sns
    12import os
    13from datetime import datetime
    14
    15# 支持中文显示
    16plt.rcParams['font.sans-serif'] = ['SimHei']
    17plt.rcParams['axes.unicode_minus'] = False
    18
    19INPUT_FILE = "output/raw_air_quality.csv"
    20OUTPUT_DIR = "output/plots"
    21os.makedirs(OUTPUT_DIR, exist_ok=True)
    22
    23def load_data():
    24 df = pd.read_csv(INPUT_FILE)
    25 df['timestamp'] = pd.to_datetime(df['timestamp'])
    26 return df
    27
    28def clean_data(df):
    29 """数据清洗"""
    30 # 1. 缺失值:保留 NaN,不强行填充(因是快照数据)
    31 print("缺失值统计:")
    32 print(df.isnull().sum())
    33
    34 # 2. 异常值:简单过滤(AQI > 500 视为异常)
    35 df = df[df['aqi'] <= 500]
    36 df = df[df['aqi'] >= 0]
    37
    38 return df
    39
    40def plot_aqi_comparison(df):
    41 """城市 AQI 对比柱状图"""
    42 plt.figure(figsize=(10, 6))
    43 sns.barplot(data=df, x='city', y='aqi', palette='viridis')
    44 plt.title('各城市当前 AQI 指数对比')
    45 plt.xticks(rotation=30)
    46 plt.tight_layout()
    47 plt.savefig(os.path.join(OUTPUT_DIR, 'aqi_comparison.png'), dpi=150)
    48 plt.show()
    49
    50def plot_pollutant_boxplot(df):
    51 """污染物分布箱线图"""
    52 pollutants = ['pm25', 'pm10', 'o3', 'no2']
    53 df_melt = df.melt(id_vars=['city'], value_vars=pollutants, var_name='Pollutant', value_name='Value')
    54
    55 plt.figure(figsize=(12, 6))
    56 sns.boxplot(data=df_melt, x='Pollutant', y='Value', palette='Set2')
    57 plt.title('主要污染物浓度分布(箱线图)')
    58 plt.tight_layout()
    59 plt.savefig(os.path.join(OUTPUT_DIR, 'pollutant_boxplot.png'), dpi=150)
    60 plt.show()
    61
    62def main():
    63 df = load_data()
    64 print("原始数据形状:", df.shape)
    65 df_clean = clean_data(df)
    66 print("清洗后数据形状:", df_clean.shape)
    67
    68 # 保存清洗后数据
    69 df_clean.to_csv("output/cleaned_air_quality.csv", index=False, encoding="utf-8-sig")
    70
    71 # 生成图表
    72 plot_aqi_comparison(df_clean)
    73 plot_pollutant_boxplot(df_clean)
    74
    75 print("✅ 所有图表已保存至 output/plots/")
    76
    77if __name__ == "__main__":
    78 main()


    ▶️ 如何运行?

  • 申请 WAQI Token
    👉 https://aqicn.org/data-platform/token/

  • 替换代码中的 TOKEN

    1TOKEN = "你的token"

  • 安装依赖

    1pip install -r requirements.txt

  • 运行

    1python waqi_city_history.py
    2python analysis.py


  • ❓ 常见问题

    Q:为什么只有一条数据?
    A:免费 API 仅返回最新快照。若需时间序列,请每天运行一次脚本,或使用高级历史接口(需授权)。

    Q:城市名写错怎么办?
    A:城市 slug 请参考 WAQI 网址,如 https://aqicn.org/city/beijing/ → slug 为 beijing。

    Q:中文显示乱码?
    A:确保系统有 SimHei 字体,或改用 plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']。

     


    ❤️ 结语

    虽然 WAQI 的 API 有一定门槛,但通过合理设计,我们依然能构建出实用的数据 pipeline。希望这套代码能成为你空气质量分析的起点!

    欢迎 点赞 + 收藏 + 关注,也欢迎在评论区交流改进方案(如加入定时任务、数据库存储、Flask 展示等)!

    作者:晨敛星河
    声明:代码原创,仅用于学习交流。

     

    赞(0)
    未经允许不得转载:171主机测评 » 基于 WAQI API 的空气质量数据智能采集与预处理系统(Python + pandas)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址