You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python+OpenWeatherMap+Flet天气应用遇'daily' KeyError及日期获取问题

问题解决:OpenWeatherMap 无daily字段报错+日期重复问题

核心问题拆解

  1. KeyError: 'daily':你当前调用的是/weather接口(仅返回当前天气),这个接口的响应里根本没有daily字段。要获取多日预报数据,必须用专门的预报接口。
  2. 日期重复:之前用response['dt']重复是因为误拿了当前天气的单一时间戳,或者用了每3小时更新的预报数据但没做去重。
  3. API无直接日期名称:OpenWeatherMap所有接口都不会返回“周六/周日”这类星期名称,只能通过返回的时间戳dt转换,但我们可以通过正确接口+数据处理避免重复。

解决方案

步骤1:更换为正确的预报API端点

免费版有两种可选接口,按需选择:

方案A:用/forecast接口(无需经纬度,直接用城市名)

这个接口返回5天内每3小时一条的预报数据,适合快速适配城市名查询:

API_KEY = "你的API密钥"
# 替换为预报接口地址
BASE_URL = "http://api.openweathermap.org/data/2.5/forecast?"
CITY = "Minsk"
COUNTRY = "BY"
days_en = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
days = days_en

# 拼接URL,cnt=40对应5天全量数据,units=metric可选(返回摄氏度)
url = f"{BASE_URL}appid={API_KEY}&q={CITY},{COUNTRY}&cnt=40&units=metric"
response = requests.get(url).json()

方案B:用/onecall接口(7天完整预报,需先获取经纬度)

如果需要7天完整数据,先调用/weather获取城市经纬度,再调用onecall接口:

API_KEY = "你的API密钥"
CITY = "Minsk"
COUNTRY = "BY"
days_en = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
days = days_en

# 第一步:获取城市经纬度
geo_url = f"http://api.openweathermap.org/data/2.5/weather?q={CITY},{COUNTRY}&appid={API_KEY}"
geo_response = requests.get(geo_url).json()
lat = geo_response['coord']['lat']
lon = geo_response['coord']['lon']

# 第二步:调用onecall获取7天预报,排除不需要的实时/分钟级数据
onecall_url = f"https://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={lon}&exclude=current,minutely,hourly&appid={API_KEY}"
response = requests.get(onecall_url).json()

这个方案的响应里会直接出现daily字段,完美匹配你原来的循环逻辑。


步骤2:处理日期避免重复+转换为星期名称

如果用方案A(/forecast接口)

因为接口每3小时返回一条数据,需要过滤重复日期,只保留每天的第一条数据:

def _bot_data():
    _bot_data = []
    processed_dates = set()  # 存已处理的日期,避免重复
    
    for item in response['list']:
        dt_timestamp = item['dt']
        date_obj = datetime.datetime.fromtimestamp(dt_timestamp)
        date_str = date_obj.strftime('%Y-%m-%d')  # 用日期字符串判断是否重复
        
        if date_str not in processed_dates:
            processed_dates.add(date_str)
            # 转换为星期名称(weekday()返回0=周一,对应days_en[0])
            weekday_name = days_en[date_obj.weekday()]
            
            _bot_data.append(
                Row(
                    spacing=5,
                    alignment="spaceBetween",
                    controls=[
                        Row(
                            expand=1,
                            alignment="start",
                            controls=[
                                Container(
                                    alignment=alignment.center,
                                    content=Text(weekday_name)
                                )
                            ]
                        )
                    ]
                )
            )
        # 最多取7天,提前终止循环
        if len(_bot_data) >=7:
            break
    return _bot_data

如果用方案B(/onecall接口)

接口返回的daily列表直接包含7天数据,直接修改原代码即可:

def _bot_data():
    _bot_data = []
    # range(0,7)包含当天到未来6天,要未来7天就用range(1,8)
    for index in range(0, 7):
        dt_timestamp = response['daily'][index]['dt']
        date_obj = datetime.datetime.fromtimestamp(dt_timestamp)
        weekday_name = days_en[date_obj.weekday()]
        
        _bot_data.append(
            Row(
                spacing=5,
                alignment="spaceBetween",
                controls=[
                    Row(
                        expand=1,
                        alignment="start",
                        controls=[
                            Container(
                                alignment=alignment.center,
                                content=Text(weekday_name)
                            )
                        ]
                    )
                ]
            )
        )
    return _bot_data

步骤3:清理冗余依赖

你重复导入了datetime,删掉其中一个即可:

# 保留一个导入,比如
import datetime
# 删掉 import datetime as dt

内容的提问来源于stack exchange,提问作者Vlach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:40:55