2、数据采集基础:使用requests库从公开API获取实时空气质量数据,解析JSON格式

2.1 为什么选requests?

Python里发HTTP请求的库不少,但requests绝对是最顺手的那个。我个人习惯用它,原因很简单——代码写起来像读英文一样自然。

你想想看,我们要从API拿数据,本质上就是发一个GET请求。用requests的话,一行代码就能搞定。我在项目中遇到过用urllib的同事,那代码写得...嗯,怎么说呢,看着就累。requests把那些繁琐的编码、参数拼接、异常处理都封装好了。

核心要点:requests不是Python标准库,需要单独安装。但相信我,这绝对是值得的。

2.2 安装与导入

先装库,再导入。就这么简单。

pip install requests

导入的时候,我建议你直接写:

import requests

别用from requests import *,那样容易污染命名空间。我曾经在项目里看到有人这么干,结果跟自定义的get函数冲突了,排查了半天。

2.3 第一个GET请求

好,我们来真的。找一个公开的空气质量API,比如和风天气或者AQICN。这里我用一个示例接口演示:

import requests

url = "https://api.airquality.example.com/v1/current"
params = {
    "city": "beijing",
    "token": "your_api_key_here"
}

response = requests.get(url, params=params)
print(response.status_code)
print(response.text)

看到没?params参数自动帮你拼接到URL后面。不用手动去搞?city=beijing&token=...这种字符串拼接,省心多了。

小技巧:调试的时候,可以打印response.url看看实际请求的完整URL,方便确认参数对不对。

2.4 解析JSON数据

API返回的通常是JSON格式。说白了就是一段结构化的文本,长得像Python字典。requests内置了JSON解析器,直接调用.json()方法就行。

data = response.json()
print(data["data"]["aqi"])  # 假设返回结构是 {"data": {"aqi": 85}}

为什么会这样设计?因为JSON和Python字典几乎一一对应,解析起来毫无压力。我在做数据采集时,经常先打印data.keys()看看顶层有哪些字段,再一层层往下挖。

2.5 处理常见问题

实际项目中,API不可能每次都乖乖返回数据。我遇到过的情况多了去了:

  • 网络超时:设置timeout参数,别让程序卡死
  • 状态码非200:检查response.status_code,404、500都要处理
  • JSON解析失败:用try-except包一下,防止程序崩溃
try:
    response = requests.get(url, params=params, timeout=5)
    response.raise_for_status()  # 状态码不是200就抛异常
    data = response.json()
except requests.exceptions.Timeout:
    print("请求超时了,换个时间再试")
except requests.exceptions.HTTPError as e:
    print(f"HTTP错误:{e}")
except ValueError:
    print("返回的不是合法JSON")

注意:我曾经在生产环境里忘了加timeout,结果某个API挂了,整个采集任务卡了半小时。从那以后,timeout成了我代码里的标配。

2.6 实战:采集北京实时AQI

来,我们写一个完整的例子。假设你拿到了某个免费API的key:

import requests

def fetch_aqi(city="beijing"):
    url = "https://api.airquality.example.com/v1/current"
    params = {
        "city": city,
        "token": "your_real_token"
    }
    
    resp = requests.get(url, params=params, timeout=5)
    resp.raise_for_status()
    
    result = resp.json()
    aqi = result["data"]["aqi"]
    pm25 = result["data"]["pm25"]
    pm10 = result["data"]["pm10"]
    
    print(f"{city} 当前AQI:{aqi}")
    print(f"PM2.5:{pm25} μg/m³")
    print(f"PM10:{pm10} μg/m³")
    
    return result["data"]

if __name__ == "__main__":
    fetch_aqi()

这个函数返回的是字典,后面做数据清洗、存数据库都很方便。你想想看,从发请求到拿到结构化数据,总共才几行代码?

2.7 数据字段说明

不同API返回的字段名可能不一样,但核心数据大同小异。我整理了一个常见字段对照表:

字段名 含义 示例值
aqi 空气质量指数 85
pm25 PM2.5浓度 (μg/m³) 35.2
pm10 PM10浓度 (μg/m³) 68.7
o3 臭氧浓度 (μg/m³) 120.5
no2 二氧化氮浓度 (μg/m³) 45.0
co 一氧化碳浓度 (mg/m³) 1.2
so2 二氧化硫浓度 (μg/m³) 8.5
timestamp 数据采集时间 2024-01-15 14:00:00

经验之谈:拿到数据后,先检查timestamp字段。有些API返回的是UTC时间,需要转成北京时间(UTC+8)。我踩过这个坑,数据展示出来差了8个小时,用户投诉说数据不对。

2.8 本章小结

说白了,数据采集就三步:发请求、拿响应、解析JSON。requests库让这三步变得异常简单。你只要记住:

  • params传参,别手动拼URL
  • timeout,别让程序死等
  • .json()解析,别自己写解析器
  • 异常处理要到位,别裸奔

下一章,我们会把采集到的数据存到本地,为后续的数据清洗和可视化做准备。嗯,到时候你会看到,数据采集只是万里长征第一步。