はじめに
なにか作りたいなと思い、主にpythonで天気情報取得アプリを作ってみました。
TkEasyGUIを用いてGUIを実装し、 画面から操作出来るようにしてみました。
初めて記事を書くので、お手柔らかにお願いします
経緯
「新しく言語勉強したい」
「無性に何か作りたい」
「天気情報を取得できるの面白い!」
で作成に至ります。
全体の構成
画面
TkEasyGUIを使って、2つの画面を作成しています。
①天気情報取得画面
②場所コード検索画面
コード
①GUI.py(画面表示)
②get_weather.py(天気情報取得)
③search.py(場所コード検索)
以上のようになっています!
コード
画面側
#TkEasyGUIをインポート
import TkEasyGUI as sg
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import get_weather as gw
import search as sr
#テーマ設定
style = ttk.Style()
style.theme_use('classic')
# Frame要素のスタイル設定
style.configure('TFrame', borderwidth=5, relief = 'solid')
#コンポーネント設定
layout1 = [ [sg.Text('天気予報')],
[sg.Text('場所コードと、予報日を教えてください。')],
[sg.Text('場所', key = 'city_cd'), sg.Button('参照', key = 'ref'),
sg.InputText('', key = 'city'),sg.Text('予報日'), sg.Combo((['今日', '明日', '明後日']), default_value = '今日', key = 'day')],
[sg.Button('OK', key = 'read'), sg.Button('キャンセル', key = 'cancel')],
[sg.Text(key = 'output', size = (40, 5))] ]
#ウィンドウの生成
window1 = sg.Window('天気予報', layout1)
# Output用のTextウィジェットを特定 (最後の要素)
output_text = layout1[-1][0]
result_text = layout1[2][2]
try:
#イベントループ
while True:
event1, values1 = window1.read()
if event1 == 'ref':
#-------------
#参照画面(window2)を開く
#-------------
layout2 = [ [sg.Text('場所コード検索')],
[sg.InputText('', key = 'suggest'), sg.Button('検索', key = 'search')],
[sg.Text('', key = 'cd', size = (17, 1)), sg.Button('選択', key = 'choice')] ]
#検索結果表示要素の指定
display_text = layout2[2][0]
#検索結果用変数
conseq = ''
window2 = sg.Window('場所コード検索', layout2, size = (500, 500))
while True:
event2, values2 = window2.read()
if event2 == sg.WIN_CLOSED:
break
elif event2 == 'search':
conseq = sr.city_search(values2['suggest'])
display_text.update(conseq)
if event2 == 'choice':
if conseq == '' or display_text == '':
messagebox.showwarning("警告", "検索を実行してください。")
if conseq != '':
result_text.update(conseq)
window2.close()
break
window2.close()
if event1 == sg.WIN_CLOSED:
break
if event1 == 'cancel':
break
if event1 == 'read':
if values1['city'] == '' or values1['day'] == '':
messagebox.showwarning("警告", "情報を入力してください。")
continue
if values1['day'] == '今日':
values1['day'] = 0
elif values1['day'] == '明日':
values1['day'] = 1
else:
values1['day'] = 2
result = gw.get_weather_info(values1['city'], int(values1['day']))
#print(result) #printはあくまでコンソールに出力
output_text.update(result)
window1.close()
except Exception as e:
print(f"エラーが発生しました:{e}")
天気情報取得
#HTTPリクエストを行うための「requests」ライブラリをインポート
import requests
import datetime
#天気情報取得メソッド
def get_weather_info(city_no, day):
try:
#リクエストurlを作成
url = f"https://weather.tsukumijima.net/api/forecast?city={city_no}"
#レスポンスを辞書形式に変換して取得
response_data = requests.get(url).json()
#天候の情報を取得 ※forecastsをキーに指定
weather_data = response_data["forecasts"][day]
#各情報を取得
date = weather_data['date'] #日付
title = response_data['title'] #タイトル
weather = weather_data['telop'] #天候情報
max_temp = weather_data['temperature']["max"]["celsius"] #最高気温
min_temp = weather_data['temperature']["min"]["celsius"] #最低気温
#現在時刻取得
now = datetime.datetime.now().time().strftime("%H:%M")
# 明日の降水確率(平均値)
chanceOfRainOfKey = weather_data['chanceOfRain']
#今日日付の場合
if day == 0:
#過ぎた時間以外の降水確率を取得する
if now <= "06:00" and chanceOfRainOfKey['T00_06'] != '--%':
chanceOfRainList = {
"T00_06": int(chanceOfRainOfKey['T00_06'].replace('%', ''))
}
if now <= "12:00" and chanceOfRainOfKey['T06_12'] != '--%':
chanceOfRainList = {
"T06_12": int(chanceOfRainOfKey['T06_12'].replace('%', ''))
}
if now <= "18:00" and chanceOfRainOfKey['T12_18'] != '--%':
chanceOfRainList = {
"T12_18": int(chanceOfRainOfKey['T12_18'].replace('%', ''))
}
if now <= "24:00" and chanceOfRainOfKey['T18_24'] != '--%':
chanceOfRainList = {
"T18_24": int(chanceOfRainOfKey['T18_24'].replace('%', ''))
}
#今日以外の未来日付の場合
else:
chanceOfRainList = {
"T00_06": int(chanceOfRainOfKey['T00_06'].replace('%', '')),
"T06_12": int(chanceOfRainOfKey['T06_12'].replace('%', '')),
"T12_18": int(chanceOfRainOfKey['T12_18'].replace('%', '')),
"T18_24": int(chanceOfRainOfKey['T18_24'].replace('%', ''))
}
#降水確率の平均を計算
avgChanceOfRain = sum(chanceOfRainList.values()) / len(chanceOfRainList)
minTempMsg = ("最低気温を取得することが出来ませんでした" if min_temp is None else f"最低気温は{min_temp}度です")
results = f"{date}の{title}は、{weather}です。\n最高気温は{max_temp}度\n{minTempMsg}。\n降水確率は{avgChanceOfRain}%です。"
return results
except requests.exceptions.RequestException as e:
return f"天気情報の取得に失敗しました: {e}"
except KeyError as e:
return f"キーが見つかりません: {e}"
print(get_weather_info('090010', 0))
検索処理※別画面
def city_search(city_name):
# 辞書の作成
codes = {'仙台': '040010',
'東京': '130010',
'千葉': '120010',
'宇都宮': '090010',
'大阪': '270000'}
value = city_name
if value in codes:
return codes.get(value)
挙動
以上です!
検索画面を経由しなくても、そのまま場所コードを入力すれば天気情報取得は可能です。
まとめ
初めてpythonで一通りの機能を持ったものを実装しました。GUIというものも知ることができ、よい経験でした...
今回は天気情報取得のために場所コードを辞書型変数で用意していますが、情報量が多くなると見にくいだろうし、処理も遅くなるかもしれません。pythonを使って、データベースも触りたいなあと思っています。
コードを行う上で、わからない所をQiitaで質問したときに答えてくださった方がいました。お力添えありがとうございます。
さて、次は何を作りましょう。
参考
https://qiita.com/07aikiro/items/de209cb8732362e3f103
https://note.com/programming_sc/n/ndb4a56b7373c
https://qiita.com/sesame/items/93acd90803c8f9edfdfb