0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pythonとTkeasyGUIで天気情報取得アプリを作る

Posted at

はじめに

なにか作りたいなと思い、主にpythonで天気情報取得アプリを作ってみました。

TkEasyGUIを用いてGUIを実装し、 画面から操作出来るようにしてみました。

初めて記事を書くので、お手柔らかにお願いします:sweat_smile:

経緯

「新しく言語勉強したい」
「無性に何か作りたい」
「天気情報を取得できるの面白い!」

で作成に至ります。

全体の構成

画面

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)

挙動

・画面表示

・参照ボタンを押下して、検索画面を表示

・検索を実施。そして「選択」ボタンをクリック。

・元画面の場所テキストボックスに検索したコードが入る。

・そのまま「OK」ボタン押下で、天気情報を取得して表示。

以上です!

検索画面を経由しなくても、そのまま場所コードを入力すれば天気情報取得は可能です。

まとめ

初めてpythonで一通りの機能を持ったものを実装しました。GUIというものも知ることができ、よい経験でした...:hugging:

今回は天気情報取得のために場所コードを辞書型変数で用意していますが、情報量が多くなると見にくいだろうし、処理も遅くなるかもしれません。pythonを使って、データベースも触りたいなあと思っています。

コードを行う上で、わからない所をQiitaで質問したときに答えてくださった方がいました。お力添えありがとうございます。

さて、次は何を作りましょう。

参考

https://qiita.com/07aikiro/items/de209cb8732362e3f103
https://note.com/programming_sc/n/ndb4a56b7373c
https://qiita.com/sesame/items/93acd90803c8f9edfdfb

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?