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()解析,别自己写解析器 - 异常处理要到位,别裸奔
下一章,我们会把采集到的数据存到本地,为后续的数据清洗和可视化做准备。嗯,到时候你会看到,数据采集只是万里长征第一步。