【Python入门】用 requests 调 API 获取天气数据,一周学完 Python 基础

学 Python 一周能做什么?这篇文章带你从零调天气 API,用类封装成 Weather_manage,最后回顾第一周 7 天的学习成果。

一、先看问题

想获取任意城市的实时天气数据,怎么做?

输入:城市名 "Beijing"
输出:气温 23.45°C,湿度 45%,风速 3.5m/s ...

答案:调天气 API,用 Python 解析返回的 JSON 数据。

二、requests 基础:5 分钟学会调 API

1. HTTP 请求方法

方法 用途 类比
GET 获取数据 打开网页看内容
POST 提交数据 填表单提交
PUT 修改数据 编辑已有内容
DELETE 删除数据 删除一条记录

2. 发送请求

import requests

url = 'https://api.example.com/data'
params = {'key': 'value'}  # GET 请求参数

response = requests.get(url, params=params, timeout=5)

3. response 对象常用属性

属性 说明 示例
status_code 状态码 200 成功,404 未找到,500 服务器错误
text 文本内容 '{"temp": 23}'
json() 解析为字典 {'temp': 23}
encoding 编码格式 'utf-8'
headers 响应头 {'Content-Type': 'application/json'}

4. 异常处理

try:
    response = requests.get(url, params=params, timeout=5)
    if response.status_code == 200:
        data = response.json()
        print(data)
    else:
        print(f'请求失败,状态码:{response.status_code}')
except Exception as e:
    print(f'请求出错:{e}')

💡 timeout=5 表示 5 秒没响应就超时,防止程序卡死。

三、实战:获取天气数据

我使用的是 OpenWeatherMap,需要先注册账号获取 API Key。

第 1 版:直接调 API,打印原始数据

import requests

params = {'q': 'Beijing', 'appid': '你的API Key'}
url = 'https://api.openweathermap.org/data/2.5/weather'

response = requests.get(url, params=params)
print(response.json())

输出一大堆 JSON,看不懂?没关系,下一步提取关键信息。

第 2 版:解析 JSON,提取关键信息

def get_weather(city='Beijing'):
    params = {'q': city, 'appid': '你的API Key'}
    url = 'https://api.openweathermap.org/data/2.5/weather'
    mydata = {}
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            mydata['城市'] = data.get('name', '未知')
            mydata['天气'] = data['weather'][0]['description']
            mydata['气温'] = data['main']['temp']
            mydata['湿度'] = data['main']['humidity']
            mydata['风速'] = data['wind']['speed']
    except Exception as e:
        print(f'请求出错:{e}')
    return mydata

print(get_weather('Beijing'))
# → {'城市': 'Beijing', '天气': 'clear sky', '气温': 296.45, ...}

等等,气温 296.45?这是开尔文!不是摄氏度!

第 3 版:开尔文转摄氏度

def K2C(kelvin):
    """开尔文转摄氏度,保留2位小数"""
    return f'{(kelvin - 273.15):.2f}'

print(K2C(296.45))  # → '23.30'

⚠️ 踩坑:OpenWeatherMap 默认返回开尔文温度,不是摄氏度!需要在请求参数加 units=metric 才能直接获取摄氏度,或者自己写转换函数。

四、用类封装:Weather_manage

为什么要用类?

# 函数写法:每次都要传 url 和 appid
get_weather('Beijing', url='...', appid='...')
get_weather('Shanghai', url='...', appid='...')

# 类写法:url 和 appid 只需初始化一次
wm = Weather_manage(appid='你的API Key')
wm.get_weather('Beijing')
wm.get_weather('Shanghai')
wm.save_to_json('Beijing')  # 还能直接保存文件

类 = 把重复的参数和逻辑打包,用起来更简洁。

Weather_manage 完整代码

import json
import requests

class Weather_manage(object):
    def __init__(self, appid):
        self.__url = 'https://api.openweathermap.org/data/2.5/weather'
        self.__appid = appid
        self.result = {}  # ← 实例变量,每个对象独立

    def _parse_weather(self, data):
        """解析天气数据(私有方法,避免重复代码)"""
        self.result['城市'] = data.get('name', '未知')
        self.result['天气'] = data['weather'][0]['description']
        self.result['气温'] = self.K2C(float(data['main']['temp']))
        self.result['体感温度'] = self.K2C(float(data['main']['feels_like']))
        self.result['最低温'] = self.K2C(float(data['main']['temp_min']))
        self.result['最高温'] = self.K2C(float(data['main']['temp_max']))
        self.result['湿度'] = data['main']['humidity']
        self.result['风速'] = data['wind']['speed']
        self.result['风向'] = data['wind'].get('deg', 'N/A')
        return self.result

    def getWeatherByCity(self, city='Beijing'):
        params = {'q': city, 'appid': self.__appid}
        try:
            response = requests.get(url=self.__url, params=params)
            if response.status_code == 200:
                return self._parse_weather(response.json())
        except Exception as e:
            print(f'请求出错:{e}')
        return {}

    def getWeatherByLatAndLon(self, lat=44.34, lon=10.99):
        params = {'lat': lat, 'lon': lon, 'appid': self.__appid}
        try:
            response = requests.get(url=self.__url, params=params)
            if response.status_code == 200:
                return self._parse_weather(response.json())
        except Exception as e:
            print(f'请求出错:{e}')
        return {}

    def save_to_json(self, city='Beijing'):
        """获取天气并保存为 JSON 文件"""
        self.getWeatherByCity(city)
        filename = city + '.json'
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(self.result, f, ensure_ascii=False, indent=2)

    def K2C(self, kelvin):
        """开尔文转摄氏度"""
        return f'{(kelvin - 273.15):.2f}'

使用示例

wm = Weather_manage(appid='你的API Key')

# 按城市查询
beijing = wm.getWeatherByCity('Beijing')
print(beijing)
# → {'城市': 'Beijing', '天气': 'clear sky', '气温': '23.30', ...}

# 按经纬度查询
loc = wm.getWeatherByLatAndLon(lat=39.9, lon=116.4)

# 保存为 JSON 文件
wm.save_to_json('Beijing')  # → Beijing.json

类变量 vs 实例变量的坑

# ❌ 错误:result 定义在类里(类变量),所有实例共享
class Weather_manage:
    result = {}  # 所有对象共享同一个 result!

w1 = Weather_manage()
w2 = Weather_manage()
w1.getWeatherByCity('Beijing')
w2.getWeatherByCity('Shanghai')
print(w1.result)  # → 上海的数据!北京的被覆盖了!

# ✅ 正确:result 定义在 __init__ 里(实例变量),每个实例独立
class Weather_manage:
    def __init__(self):
        self.result = {}  # 每个对象独立的 result

w1 = Weather_manage()
w2 = Weather_manage()
w1.getWeatherByCity('Beijing')
w2.getWeatherByCity('Shanghai')
print(w1.result)  # → 北京的数据 ✅

五、踩坑记录

坑 1:API 返回的温度是开尔文

data['main']['temp']  # → 296.45(开尔文,不是摄氏度!)

解决:写 K2C() 转换函数,或在请求参数加 units=metric

坑 2:类变量 result 被多个实例共享

result = {} 写在类里是类变量,所有实例共享同一个字典。必须放在 __init__ 里变成实例变量。

坑 3:JSON 保存中文乱码

# ❌ 中文变成 \uXXXX
json.dump(data, f)

# ✅ 加 ensure_ascii=False 保留中文
json.dump(data, f, ensure_ascii=False, indent=2)

六、第一周总结

学了什么 做了什么
Day 1 变量、运算符、字符串 计算器
Day 2 数据结构、推导式 词频统计
Day 3 流程控制 猜数字游戏
Day 4 函数、闭包、装饰器 闭包陷阱实验
Day 5 文件读写、CSV/JSON 学生成绩计算
Day 6 类、继承、多态 FileManager 类
Day 7 requests 调 API Weather_manage 类

7 天从零基础到能用类封装 API 调用,这就是每天 8 小时的力量。

七、下一步:SQL + PostgreSQL

📌 Python 基础告一段落,接下来进入数据工程的核心——SQL。下一篇:SQL 入门,从 SELECT 到 JOIN。

更多推荐