質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

864閲覧

OpenWeatherMap apiを使用した天気予報を取得する関数作成で発生したエラーを解消したい.

kokou

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/09/04 09:58

編集2023/09/04 11:21

実現したいこと

OpenWeatherMap APIから任意の気象予報データを取得したいです.

前提

最近プログラミング,pythonを勉強し始めた人間です.
初めて質問させていただくため,情報不足など至らない点があるかもしれませんが,ご了承ください.
基礎を勉強し,現在は最高気温や最低気温,降水確率を取得し,任意の時間にLINEに表示するbotを作成中です.
apiから気象予報データを取得するコードがある程度書けたため,試しに東京の3時間後の予報の取得を試みました.
するとエラーが発生し,色々調べましたが理由が分からず,困惑しています.
どなたか分かる方がいらっしゃったら助けてください.

OpenWeatherMap APIで取得できるjson形式のapi応答フィールドは以下の通りとなります.

cod:内部パラメータ
message:内部パラメータ
cntAPI :応答で返されるタイムスタンプの数
list
ーlist.dt :予測されたデータの時刻 (UNIX、UTC)
ーlist.main
ーーーlist.main.temp:温度
ーーーlist.main.feels_likeこの温度パラメータは、人間の天候の認識を説明しています。
ーーーlist.main.temp_min:計算時の最低気温
ーーーlist.main.temp_max:計算時の最高温度。
ーーーlist.main.pressure:デフォルトの海面大気圧
ーーーlist.main.sea_level:海面上の大気圧
ーーーlist.main.grnd_level:地上の大気圧
ーーーlist.main.humidity:湿度
ーーーlist.main.temp_kf:内部パラメータ
ーlist.weather
ーーーlist.weather.id:気象条件 ID
ーーーlist.weather.main:気象パラメータのグループ(雨、雪、雲など)
ーーーlist.weather.description:グループ内の気象条件(晴れ,快晴など)
ーーーlist.weather.icon:天気アイコン ID
ーlist.clouds
ーーーlist.clouds.all:曇り度
ーlist.wind
ーーーlist.wind.speed:風速
ーーーlist.wind.deg:風向
ーーーlist.wind.gust:突風
ーーーlist.visibility:平均視程
ーーーlist.pop:降水確率
ーlist.rain
ーーーlist.rain.3h:過去3時間の雨量
ーlist.snow
ーーーlist.snow.3h:過去3時間の積雪量
ーlist.sys
ーーーlist.sys.pod:一日の一部(n - 夜、d - 日)
ーlist.dt_txt:予測されるデータの時刻、ISO、UTC
city
ーcity.id :市区町村 ID
ーcity.name 市区町村名
ーcity.coord
ーーcity.coord.lat :緯度
ーーcity.coord.lon:経度
ーcity.country :国コード(GB、JPなど)
ーcity.population市の人口
ーcity.timezone:UTC からの秒単位のシフト
ーcity.sunrise:日の出時刻 (ユニックス、UTC)
ーcity.sunset:サンセット時間, ユニックス, UTC

発生している問題・エラーメッセージ

KeyError: 'weather'

該当のソースコード

python

1#天気予報を取得する関数 2def get_weather(latitude,longitude): 3 #OpenWeatherMap APIキー 4 api_key = '{my_api_key}' 5 #url作成 6 endpoint = 'https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&units=metric&lang=ja&appid={api_id}&cnt={limit}' 7 #取得する予報時刻の数 8 request_line = 1 9 url = endpoint.format(lat = latitude , lon = longitude , api_id = api_key , limit = request_line) 10 #APIから情報を取得(レスポンス) 11 response = requests.get(url) 12 #レスポンスの内容をJSONフォーマットからPythonフォーマットに変換 13 response = response.json() 14 #気象情報の取得 15 climate = response['weather'][0]['description'] 16 temp_max = response['main']['temp_max'] 17 temp_min = response['main']['temp_min'] 18 precipitation = response['pop'] 19 #出力 20 print(f'{weather}の予報です.') 21 print(f'最高気温は{temp_max}℃です.') 22 print(f'最低気温は{temp_min}℃です.') 23 print(f'降水確率は{precipitation}%です.') 24 if precipitation <= 0.5 : 25 print('傘を持ち歩いた方が良いでしょう.お出かけの際は忘れずに!') 26 else : 27 print('傘は必要ありません.') 28get_weather(35.6813,139.766)

試したこと

15行目の
climate = response['weather'][0]['description']
で発生していますが,この行全体をコメントアウトすると15行目で
Keyerror: 'main'
と出てきます.

responseの中身は以下の通りでした.
{'cod': '200', 'message': 0, 'cnt': 1, 'list': [{'dt': 1693828800, 'main': {'temp': 28.34, 'feels_like': 34.25, 'temp_min': 27.81, 'temp_max': 28.34, 'pressure': 1010, 'sea_level': 1010, 'grnd_level': 1008, 'humidity': 87, 'temp_kf': 0.53}, 'weather': [{'id': 500, 'main': 'Rain', 'description': '小雨', 'icon': '10n'}], 'clouds': {'all': 75}, 'wind': {'speed': 2.86, 'deg': 182, 'gust': 3.93}, 'visibility': 10000, 'pop': 0.62, 'rain': {'3h': 1.24}, 'sys': {'pod': 'n'}, 'dt_txt': '2023-09-04 12:00:00'}], 'city': {'id': 1857654, 'name': '東京都千代田区丸の内', 'coord': {'lat': 35.6813, 'lon': 139.766}, 'country': 'JP', 'population': 0, 'timezone': 32400, 'sunrise': 1693772087, 'sunset': 1693818368}}

見ていただいたら分かる通り,weatherは存在しています.

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2023/09/04 10:12

> KeyError: 'weather' 辞書responseのキーとして'weather'がないんでしょうね。
meg_

2023/09/04 10:14

> apiから気象予報データを取得するコードがある程度書けたため, どんなコードでしたらエラーなく実行できましたか?
kokou

2023/09/04 10:19

回答ありがとうございます! >> 辞書responseのキーとして'weather'がないんでしょうね。 私もそう思うのですが,他に同じようなコードを書かれている方はこのコードでエラー無く実行できているようでして,なぜ私の場合はエラーが出るのかが分かりません. >>どんなコードでしたらエラーなく実行できましたか? 14行目以降をコメントアウトして print(response) としたら,エラーは発生しませんでした.
meg_

2023/09/04 10:40

> 他に同じようなコードを書かれている方はこのコードでエラー無く実行できているようでして ご自身の(環境での)コードでデバッグしないと問題は解決しないと思います。 まずresponseのキーとして存在しているものは何なのか?を確認するところからではないでしょうか。
kokou

2023/09/04 11:07

キーとして存在しているものは前提に書きましたapi取得フィールドだと思います.分かりにくくてすみません.公式サイトに書かれていたものをコピペしました.ここを見ると'weather'や'main'など存在しているため,なぜエラーが発生するのか分かりません.
meg_

2023/09/04 11:47

> 見ていただいたら分かる通り,weatherは存在しています. responseのキーとして存在しているものは 'cod', 'message', 'cnt', 'list', 'city' です。
guest

回答2

0

ベストアンサー

見ていただいたら分かる通り,weatherは存在しています.

responseのキーとして存在しているものは 'cod', 'message', 'cnt', 'list', 'city' です。responseの中身に'weather'が存在していたとしてもそれはresponseのキーとしては存在していないのでキーとしては使用できません。

例えば「 '小雨'」を取り出すには

Python

1response['weather'][0]['description']

ではなく

Python

1response['list'][0]['weather'][0]['description']

と書く必要があります。

投稿2023/09/04 11:53

編集2023/09/04 11:58
meg_

総合スコア10912

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kokou

2023/09/04 12:12

回答ありがとうございます! 無事改善できました! 基礎知識が不足していることを痛感しました.もっと勉強したいと思います. 何度もコメントにて解答していただき,ありがとうございました!
guest

0

pythonを勉強中とのことですので、解決のきっかけを1つ。

python

1 response = response.json() 2 #気象情報の取得 3 climate = response['weather'][0]['description']

エラーはこの下の行で起きていて、「KeyError: 'weather'」とあるように、responseに入っている辞書に'weather'という キーが無いと言っているわけです。
あるはずのものが無いのであれば、中を見てみればいいのです。responseは 上の行で取得しているのですから、その下で

  • debug実行して取得後のresponseの中身を確認する。
  • debugできないのであれば、print(response)などとして表示してみる

と、問題の原因が1つわかるでしょう。

また、

この行全体をコメントアウトする

とあるように、問題のある行を省いてみるのは意味が無いことが多いです。
その行は必要だからあるのだし、そもそもその行が原因ではなくその前に原因があるので、その行を無くしてしまえば、問題ほ増やしているだけだからです。


BAついていますが、コメントいただいたので追記します。

質問前に内容は見てみたとのこと。ですが、もしかして、以下のような形のまま見ていたのでしょうか?

json

1{'cod': '200', 'message': 0, 'cnt': 1, 'list': [{'dt': 1693828800, 'main': {'temp': 28.34, 'feels_like': 34.25, 'temp_min': 27.81, 'temp_max': 28.34, 'pressure': 1010, 'sea_level': 1010, 'grnd_level': 1008, 'humidity': 87, 'temp_kf': 0.53}, 'weather': [{'id': 500, 'main': 'Rain', 'description': '小雨', 'icon': '10n'}], 'clouds': {'all': 75}, 'wind': {'speed': 2.86, 'deg': 182, 'gust': 3.93}, 'visibility': 10000, 'pop': 0.62, 'rain': {'3h': 1.24}, 'sys': {'pod': 'n'}, 'dt_txt': '2023-09-04 12:00:00'}], 'city': {'id': 1857654, 'name': '東京都千代田区丸の内', 'coord': {'lat': 35.6813, 'lon': 139.766}, 'country': 'JP', 'population': 0, 'timezone': 32400, 'sunrise': 1693772087, 'sunset': 1693818368}}

jsonは複雑な構造をしている場合があるので、このなかに「weather」というキーが見えるからといって、それがトップレベルにあるかどうかはわかりません。こういう場合は、構造がわかるように整形して みてみるべきでしょう。
このように整形することを pritty print とも言います。 エディタにも機能が付いていることもありますし、 オンラインの整形ツールもいくつも提供されています。 「json 整形」とか「 json pretty print」とかで検索すればいろいろみつかります。
このようにしてみれば、どのような構造で、どのようにアクセスすれば求める情報を得ることができるかわかるでしょう。

json

1{ 2 "cod": "200", 3 "message": 0, 4 "cnt": 1, 5 "list": [ 6 { 7 "dt": 1693828800, 8 "main": { 9 "temp": 28.34, 10 "feels_like": 34.25, 11 "temp_min": 27.81, 12 "temp_max": 28.34, 13 "pressure": 1010, 14 "sea_level": 1010, 15 "grnd_level": 1008, 16 "humidity": 87, 17 "temp_kf": 0.53 18 }, 19 "weather": [ 20 { 21 "id": 500, 22 "main": "Rain", 23 "description": "小雨", 24 "icon": "10n" 25 } 26 ], 27 "clouds": { 28 "all": 75 29 }, 30 "wind": { 31 "speed": 2.86, 32 "deg": 182, 33 "gust": 3.93 34 }, 35 "visibility": 10000, 36 "pop": 0.62, 37 "rain": { 38 "3h": 1.24 39 }, 40 "sys": { 41 "pod": "n" 42 }, 43 "dt_txt": "2023-09-04 12:00:00" 44 } 45 ], 46 "city": { 47 "id": 1857654, 48 "name": "東京都千代田区丸の内", 49 "coord": { 50 "lat": 35.6813, 51 "lon": 139.766 52 }, 53 "country": "JP", 54 "population": 0, 55 "timezone": 32400, 56 "sunrise": 1693772087, 57 "sunset": 1693818368 58 } 59}

投稿2023/09/04 11:11

編集2023/09/04 13:10
TakaiY

総合スコア14327

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kokou

2023/09/04 11:24

回答ありがとうございます! responseの中身は確認していたのですが,weatherは存在しているため,mainやtemp_maxなどのほかのキーは存在するのか確認するため,コメントアウトをしました.その旨を記載しておらず,申し訳ありません.responseの中身を追記したため,よろしければご確認いただき,改善策を教えていただけると幸いです.
kokou

2023/09/04 13:31

追記ありがとうございます! pritty printは知りませんでした.確かに見にくいなとは感じており,DataFrameにできないかなど試行錯誤しましたが,エラー表示が出てきて,諦めていました. 大変,勉強になりました.教えていただき,ありがとうございます!
TakaiY

2023/09/04 14:07

お役にたててなにより。 vscodeなどの高機能なエディタのjson表示の機能を使うと、一部を折畳んだりできるので、より見やすくなりますよ。 > DataFrameにできないか DataFrameというのは、CSVのような、表形式のデータを効率良く処理するための仕組みです。jsonのような複雑な構造を扱うようにはできていないので、不適切ですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問