Python Forum
Tkinter weather app
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tkinter weather app
#1
Redone the tkinter weather app
This one should work in whatever part of the world your in. (If you have access google) The first was just in US.
import tkinter as tk
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
import requests
import urllib
import base64
from PIL import Image, ImageTk
from io import BytesIO


class Data:
    pass

    def clock(self):
            ''' Return clock data '''
            current = datetime.now()
            month = current.strftime('%B')
            weekday = current.strftime('%A')
            day = current.strftime('%d')
            year = current.strftime('%Y')
            hour = current.strftime('%I')
            minute = current.strftime('%M')
            second = current.strftime('%S')
            ampm = current.strftime('%p')

            return f'{weekday} {month} {day}, {year}  {hour}:{minute}:{second} {ampm}'

    def get_weather(self):
        ''' method for getting weather data from google '''

        USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
        
        # US english
        LANGUAGE = "en-US,en;q=0.5"

        session = requests.Session()
        session.headers['User-Agent'] = USER_AGENT
        session.headers['Accept-Language'] = LANGUAGE
        session.headers['Content-Language'] = LANGUAGE

        url = 'https://www.google.com/search?q=weather'

        html = session.get(url)

        soup = BeautifulSoup(html.text, 'html.parser')

        # Create a dict to hold the data and get wanted data
        result = {}
        result['Region'] = soup.find('span', attrs={'class': 'BBwThe'}).text
        result['Temperature'] = soup.find('span', attrs={'id': 'wob_tm'}).text + f'\u00b0 F'
        result['Conditions'] = soup.find('span', attrs={'id': 'wob_dc'}).text
        result['Humidity'] = soup.find('span', attrs={'id': 'wob_hm'}).text
        result['Percipitation'] = soup.find('span', attrs={'id': 'wob_pp'}).text
        result['Wind'] = soup.find('span', attrs={'id': 'wob_ws'}).text
        result['img'] = soup.find('img', id='wob_tci', src=True)['src']
        
        return result

    def getimg(self):
        ''' Method for getting and sizing image '''
        url = 'http:'+self.get_weather()['img']
        u = urllib.request.urlopen(url)
        raw = u.read()
        u.close()
        dat = base64.b64encode(bytes(raw))
        buff = BytesIO(base64.b64decode(dat))

        image = Image.open(buff)
        image = image.resize((160,160))
        return image


class Window:
    ''' Class for window display '''
    def __init__(self, parent):
        self.parent = parent
        self.parent.rowconfigure(0, weight=1)
        self.parent.columnconfigure(0, weight=1)

        container = tk.Frame(self.parent)
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)

        self.clock = tk.Label(container, text='clock', bg='#777777', fg='black')
        self.clock.grid(column=0, row=0, sticky='new', padx=4, pady=4, ipadx=4, ipady=4)
        self.clock.configure(font=(None, 14, 'normal'))

        row1 = tk.Frame(container)
        row1.grid(column=0, row=1, sticky='news')
        for i in range(2):
            row1.grid_columnconfigure(i, weight=3, uniform='columns')

        self.left = tk.Frame(row1)
        self.left['highlightbackground'] = '#555555'
        self.left['highlightcolor'] = '#555555'
        self.left['highlightthickness'] = 1
        self.left.grid(column=0, row=0, sticky='news', pady=4, padx=(4,0))
        for i in range(2):
            self.left.grid_columnconfigure(i, weight=3, uniform='columns')

        right = tk.Frame(row1)
        right.grid(column=1, row=0, sticky='news')
        right.grid_columnconfigure(0, weight=3)

        self.img_label = tk.Label(right, bg='#555555')
        self.img_label.grid(column=0, row=0, sticky='news', padx=4, pady=(4,1))

        self.condition_label = tk.Label(right, anchor='w', bg='#555555', fg='white', padx=4)
        self.condition_label.grid(column=0, row=1, sticky='news', padx=4, pady=(1,4))


class Controller:
    ''' Controller handles communications between classes '''
    def __init__(self, data, window):
        self.data = data
        self.window = window

        # Display clock
        self.window.clock.configure(text=self.data.clock())

        # Create labels
        self.labels = []
        self.info = []
        index = 0

        for key, value in self.data.get_weather().items():
            if key != 'img':
                self.labels.append(tk.Label(self.window.left, text=f'{key}:', anchor='w'))
                self.labels[index].grid(column=0, row=index, sticky='news', padx=4, pady=1)
                self.labels[index]['font'] = None, 10, 'bold'

                self.info.append(tk.Label(self.window.left, text=value, anchor='w',font=(None, 10, 'normal')))
                self.info[index].grid(column=1, row=index, sticky='news', padx=4, pady=1)
                index += 1

        last_label = tk.Label(self.window.left, text='Last updated:', anchor='w')
        last_label['font'] = None, 10, 'bold'
        last_label.grid(column=0, row=len(self.data.get_weather())-1, sticky='new', padx=4, pady=1)
        
        # Get last update time
        self.last_data = tk.Label(self.window.left, anchor='w')
        self.last_data.grid(column=1, row=len(self.data.get_weather())-1, sticky='new', padx=4, pady=1)
        self.last_data.configure(text=datetime.now().strftime('%I:%M:%S %p'))

        next_update = tk.Label(self.window.left, text='Next update:', anchor='w', font=(None, 10, 'bold'))
        next_update.grid(column=0, row=len(self.data.get_weather()), sticky='new', padx=4, pady=1)

        # Get next update time
        update_time = datetime.now() + timedelta(minutes=5)
        self.next_data = tk.Label(self.window.left, anchor='w')
        self.next_data['text'] = update_time.strftime('%I:%M:%S %p')
        self.next_data.grid(column=1, row=len(self.data.get_weather()), sticky='new', padx=4, pady=1)
        
        # Get the image
        image = self.data.getimg()
        image = ImageTk.PhotoImage(image)
        image.bakup = image

        # Get and display image and conditions text under image
        self.window.img_label.configure(image=image)
        self.window.condition_label.configure(text=self.data.get_weather()['Conditions'])
                
        #Call the updates
        self.update()
        self.update_data()

    def update(self):
        ''' Methos updates the clock '''
        self.window.clock.configure(text=self.data.clock())
        self.window.parent.after(1000, self.update)
        

    def update_data(self):
        ''' Method updates all other information '''
        data = self.data.get_weather()
        index = 0
        for key, value in data.items():
            if key != 'img':
                self.info[index].configure(text=value)
                index += 1
                
        image = self.data.getimg()
        image = ImageTk.PhotoImage(image)
        image.bakup = image
        self.window.img_label.configure(image=image)

        self.window.condition_label.configure(text=self.data.get_weather()['Conditions'])
        
        self.last_data.configure(text=datetime.now().strftime('%I:%M:%S %p'))
        time = datetime.now() + timedelta(minutes=5)
        self.next_data.configure(text=time.strftime('%I:%M:%S %p'))

        self.window.parent.after(300000, self.update_data)


if __name__ == '__main__':
    root = tk.Tk()
    root.resizable(False, False)
    controller = Controller(Data(), Window(root))
    root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  PyQt6 Version of weather app menator01 3 3,459 Jan-30-2022, 12:32 AM
Last Post: menator01
  Tkinter Weather App menator01 1 2,117 Jan-16-2022, 11:23 PM
Last Post: menator01
  Meteostat - Historical Weather and Climate Data clampr 1 3,868 May-25-2021, 04:32 PM
Last Post: Gribouillis
  Talking Weather b4iknew 0 2,222 Jan-31-2019, 08:42 PM
Last Post: b4iknew
  SCIKItlearn -Naive Bayes Accuracy (Weather Data) usman 0 3,410 Nov-07-2018, 05:25 PM
Last Post: usman
  A weather program. mcmxl22 0 2,933 Jul-30-2018, 03:19 AM
Last Post: mcmxl22

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020