Python:OpenWeatherMapAPIで天気予報データを取得


退屈なことはPythonにやらせよう』でPythonの学習をしています。
今回は第14章jsonモジュールのプロジェクト【現在の天気予報データを取得する】でプログラムを作成し実行してみました。

401 Client error

エラー発生

エラーが出る箇所がありまして、それは文字列でOpenWeatherMapのurlを指定するところ。書籍では

http://api.openweathermap.org/data/2.5/forecast/daily

となっていますが、このまま実行すると

401 Client Error

というエラーが出てしまいます。

エラーの原因は?

まずキーの打ち間違いを疑いましたが、何度見比べても間違いはなさそう。

誤植かな?と思い書籍の正誤表を確認。誤植ではないらしい。

OpenWeatherMapのサイトを確認。Freeプランで使用できるCurrent Weather 3-hour Forecast 5 daysで「How to make an API call」を確認。

どの例を見ても「daily」というディレクトリにアクセスしていないみたい。

手持ちの書籍は2020年9月発行の第7刷。すでに情報が古いのかも?あるいは、わたしが自分では気づかないところでミスをしているか、ですね。

コードの修正

サイトの例を参考にしてurlの指定を

https://api.openweathermap.org/data/2.5/weather

に変更し、?以下のパラメーターにはq、appid、lang、unitsを指定。

url = "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}&lang=ja&units=metric".format(location, APPID)

・lang=jaで日本語化(“name”、”description”、が日本語に)。
・units=metricで気温を℃化。
パラメーターについては3-hour Forecast 5 daysのGeocodingAPIに説明があります。

一旦、IDLE Shellで実行してみます。
すると、今回はrequestsモジュールのResponseオブジェクトがエラーを返さない。text属性をjsonに渡してprint関数で表示してみると、天候のデータが表示されました!


プログラム作成Ⅰ(現在の天気・気温・温度を表示)

コーディング

天候データが取得できたので、プログラムにまとめます。

基本的には書籍と同じようにコーディングをして、最後のデータを出力するところを変更し、明日・明後日の天候ではなく、現在の天気・気温・湿度を表示してみます。

書籍とは返ってくるデータの構成が違うようなので調整。
(上記のprint関数で出力された内容を見て構成を判断しています)

・キー”list”が存在しない
・天候は”weather”のリストが格納する辞書内の”main”、”descritpion”に
・気温・湿度は”main”が指す辞書内の”temp”と”humidity”がそれぞれ

データをjson.loads関数で変換し、weather_dataという変数に代入すると

# 天候とその説明
print(weather_data["weather"][0]["main"] + '-' + weather_data["weather"][0]["description"])

# 気温
print("気温:{}度".format(weather_data["main"]["temp"]))

# 湿度
print("湿度:{}%".format(weather_data["main"]["humidity"]))

windowsのcmdからこのプログラムを実行すると、無事、現在の天候・気温・湿度を表示することができました!

C:\mydir>py quickWeather.py Tokyo JP
Tokyo,JP現在の天気:
Clouds-薄い雲
気温:30.96度
湿度:62%

問題点

しかし、このプログラムでは書籍のように明日・明後日の天気を調べることができません。


プログラム作成Ⅱ(今日・明日・明後日の天気を表示)

コーディング

書籍のようなプログラムにしたいので、3-hour Forecast 5 daysの例を参考にurlの指定を変更します。

https://api.openweathermap.org/data/2.5/forecast

url = "https://api.openweathermap.org/data/2.5/forecast?q={}&appid={}&lang=ja&units=metric&cnt=24".format(location, APPID)

書籍ではパラメーターcntは3で設定されています。これはおそらく3日分ということだと思うのですが、こちらのurlでは3時間ごとのデータが返ってくるのでcntは24に指定(3日分)。
json.loads関数で変換し、それをweather_dataという変数に代入すれば

weather_data["list"][0]["weather"][0]["description"]

で当日の天候の説明が、

weather_data["list"][8]["weather"][0]["description"]

で明日の天候の説明が返ってきます。該当箇所の数値を変更すれば、好きな、日付・時間帯のデータを選択できます…。
やろうとしていることは書籍と同じです。ただキー”list”が指す値であるリストのインデックスは調整しないと、ですね。

print("{}の天気:".format(location))

print()
# 今日の天気
print(weather_data["list"][0]["dt_txt"])
print(weather_data["list"][0]["weather"][0]["main"],'-',weather_data["list"][0]["weather"][0]["description"])

print()
# 明日の天気
print(weather_data["list"][8]["dt_txt"])
print(weather_data["list"][8]["weather"][0]["main"],'-',weather_data["list"][8]["weather"][0]["description"])

print()
# 明後日の天気
print(weather_data["list"][16]["dt_txt"])
print(weather_data["list"][16]["weather"][0]["main"],'-',weather_data["list"][16]["weather"][0]["description"])

プログラムにまとめて実行すると

C:\mydir>py quickWeather2.py Tokyo JP
Tokyo,JPの天気:

2022-09-06 00:00:00
Clouds - 雲

2022-09-07 00:00:00
Clear - 晴天

2022-09-08 00:00:00
Clouds - 厚い雲

うまくできました。2022年9月6日午前8時頃です。

補足

初めてこのプログラムを実行した際は、[“list”][0]には当日午前3時の、[“list”][8]にはその翌日午前3時の気象データが入っていました。

ですが、2回目に実行した際(上記の実行時)では、[“list”][0]には当日午前0時の、[“list”][8]にはその翌日午前0時のデータでした。

せっかくなので”dt_txt”で日付と時刻を表示してみよう、と思ってコードを修正し、日を空けて再実行したらそのような結果になりました。

データを問い合わせる時刻によって、格納される最初の時間帯が変更されるのかもしれない。すみませんが、ちょっとわかりません。


最後に

わたしなりに今できる解決方法です。PythonやOpenWeatherMapAPIの扱いに詳しければ、もっと良い解決方法が見つかるのかもしれません。

以上です。読んでくださった方、ありがとうございました。

著者名書籍名出版発行年月日参照頁
著:
Al Sweigart
訳:
相川愛三
『退屈なことはPythonにやらせよう』オライリー・ジャパン初版
2017/6/1
第7刷
2020/9/4
377~
参考文献
サイト名ページタイトルURL参考にした日付
OpenWeatherMaphttps://openweathermap.org/2022/9/6
Current weather datahttps://openweathermap.org/current同上
5 day weather forecasthttps://openweathermap.org/forecast5同上
GitHub:『退屈なことはPythonにやらせよう』のリポジトリ『退屈なことはPythonにやらせよう』の正誤表https://github.com/oreilly-japan/automatestuff-ja/wiki/errata同上
参考URL

comment