Tkinter Weather App - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Tkinter Weather App (/thread-36091.html) |
Tkinter Weather App - menator01 - Jan-16-2022 I was intrigued by this post and thought I would make a tkinter weather app. #! /usr/bin/env python3 # Do the imports import tkinter as tk import tkinter.font as tkfont from bs4 import BeautifulSoup as bs import requests import urllib import base64 # Create weather class to get info class Weather: def __init__(self): # Set some vars LANGUAGE = 'en-US, en;q=0.5' 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" # session vars session = requests.Session() session.headers['User-Agent'] = USER_AGENT session.headers['Accept-Language'] = LANGUAGE session.headers['Content-Language'] = LANGUAGE # Url to google weather, get the data, use soup to parse url = 'https://www.google.com/search?lr=lang_en&ie=UTF-8&q=weather' data = session.get(url) soup = bs(data.text, 'html.parser') # Set an empty dict and grab the data we want self.results = {} self.results['region'] = soup.find('div', attrs={'id': 'wob_loc'}).text self.results['current temperature'] = soup.find('span', attrs={'id': 'wob_tm'}).text self.results['day and hour'] = soup.find('div', attrs={'id': 'wob_dts'}).text self.results['current weather'] = soup.find('span', attrs={'id': 'wob_dc'}).text self.results['precipitation'] = soup.find('span', attrs={'id': 'wob_pp'}).text self.results['humidity'] = soup.find('span', attrs={'id': 'wob_hm'}).text self.results['wind speed'] = soup.find('span', attrs={'id': 'wob_ws'}).text self.results['img'] = soup.find('img', attrs={'class': 'wob_tci', 'id': 'wob_tci'})['src'] # Create the tkinter window class class Window: def __init__(self, parent): # set the window parent and configure rows and columns self.parent = parent self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) # Initiate the weather class self.weather = Weather() # Create the main container container = tk.Frame(self.parent) container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) # Container to hold the data in our header header_container = tk.Frame(container) header_container.grid(column=0, row=0, sticky='new') header_container.grid_columnconfigure(1, weight=3) # Container for holding weather info self.info_container = tk.Frame(container) self.info_container.grid(column=0, row=1, sticky='news') for i in range(2): self.info_container.grid_columnconfigure(i, weight=3, uniform='info') # Label for the image self.img_label = tk.Label(header_container) self.img_label['image'] = self.get_image() self.img_label['relief'] = 'groove' self.img_label.grid(column=0, row=0, sticky='new') # Label for header text header = tk.Label(header_container) header['text'] = self.weather.results['region'] header['font'] = tkfont.Font(size=18, weight='bold') header['relief'] = 'groove' header['padx'] = 8 header['fg'] = 'blue' header.grid(column=1, row=0, sticky='news') # Create empty list for labels and set a counter self.labels = [] i = 0 # Loop through the dict and assign to labels for key, value in self.weather.results.items(): if key != 'region' and key != 'img': if key == 'current temperature': text = value.title() + '\u00b0' + ' F' else: text = value.title() self.labels.append([tk.Label(self.info_container, text=key.title(), anchor='w'), tk.Label(self.info_container, text=text, anchor='w')]) self.labels[i][0]['font'] = tkfont.Font(weight='bold', size=10) self.labels[i][0]['relief'] = 'groove' self.labels[i][1]['relief'] = 'groove' self.labels[i][0].grid(column=0, row=i, sticky='new', ipadx=5) self.labels[i][1].grid(column=1, row=i, sticky='new', ipadx=5) i += 1 # Call self.update to update the information self.update() # function/method for getting and returning the image def get_image(self): url = 'https:' + self.weather.results['img'] img = urllib.request.urlopen(url) raw = img.read() img.close() image = tk.PhotoImage(data=raw) image.img = image return image # Create the update function/method def update(self): self.img_label['image'] = self.get_image() i = 0 for key, value in self.weather.results.items(): if key != 'region' and key != 'img': if key == 'current temperature': text = value.title() + '\u00b0' + ' F' else: text = value.title() self.labels[i-1][1]['text'] = text i += 1 self.info_container.after(5000, self.update) def main(): root = tk.Tk() root.title('Tkinter Weather App') root['padx'] = 5 root['pady'] = 4 root.resizable(False, False) Window(root) root.mainloop() main() RE: Tkinter Weather App - menator01 - Jan-16-2022 Added a seven day forecast #! /usr/bin/env python3 # Do the imports import tkinter as tk import tkinter.font as tkfont from bs4 import BeautifulSoup as bs import requests import urllib import base64 # Create weather class to get info class Weather: def __init__(self): # Set some vars LANGUAGE = 'en-US, en;q=0.5' 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" # session vars session = requests.Session() session.headers['User-Agent'] = USER_AGENT session.headers['Accept-Language'] = LANGUAGE session.headers['Content-Language'] = LANGUAGE # Url to google weather, get the data, use soup to parse url = 'https://www.google.com/search?lr=lang_en&ie=UTF-8&q=weather' data = session.get(url) soup = bs(data.text, 'html.parser') # Set an empty dict and grab the data we want self.results = {} self.results['region'] = soup.find('div', attrs={'id': 'wob_loc'}).text self.results['current temperature'] = soup.find('span', attrs={'id': 'wob_tm'}).text self.results['last updated'] = soup.find('div', attrs={'id': 'wob_dts'}).text self.results['current weather'] = soup.find('span', attrs={'id': 'wob_dc'}).text self.results['precipitation'] = soup.find('span', attrs={'id': 'wob_pp'}).text self.results['humidity'] = soup.find('span', attrs={'id': 'wob_hm'}).text self.results['wind speed'] = soup.find('span', attrs={'id': 'wob_ws'}).text self.results['img'] = soup.find('img', attrs={'class': 'wob_tci', 'id': 'wob_tci'})['src'] # Create empty list to hold seven day data # Get the wanted data seven_day = [] days = soup.find('div', attrs={'id': 'wob_dp'}) for day in days.find_all('div', attrs={'class': 'wob_df'}): name = day.find_all('div')[0].attrs['aria-label'] image = day.find('img') temp = day.find_all('span', {'class': 'wob_t'}) high_tmp = temp[0].text low_tmp = temp[2].text seven_day.append({'name': name, 'image': image, 'high': high_tmp, 'low': low_tmp}) # Pop off the first data as we already displaying todays forecast seven_day.pop(0) # Add the list to our dict self.results['seven day'] = seven_day # Create the tkinter window class class Window: def __init__(self, parent): # set the window parent and configure rows and columns self.parent = parent self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) # Initiate the weather class self.weather = Weather() # Create the main container container = tk.Frame(self.parent) container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) # Container to hold the data in our header header_container = tk.Frame(container) header_container.grid(column=0, row=0, sticky='new') header_container.grid_columnconfigure(1, weight=3) # Container for holding weather info self.info_container = tk.Frame(container) self.info_container.grid(column=0, row=1, sticky='news') for i in range(2): self.info_container.grid_columnconfigure(i, weight=3, uniform='info') # Container for extended forecast self.seven_day_container = tk.Frame(container) self.seven_day_container['relief'] = 'groove' self.seven_day_container['highlightbackground'] = 'gray' self.seven_day_container['highlightcolor'] = 'gray' self.seven_day_container['highlightthickness'] = 1 self.seven_day_container.grid(column=0, row=2, sticky='new') for i in range(len(self.weather.results['seven day'])): self.seven_day_container.grid_columnconfigure(i, weight=3, uniform='days') # Label for the image self.img_label = tk.Label(header_container) self.img_label['image'] = self.get_image(self.weather.results['img']) self.img_label['relief'] = 'groove' self.img_label.grid(column=0, row=0, sticky='new') # Label for header text header = tk.Label(header_container) header['text'] = self.weather.results['region'] header['font'] = tkfont.Font(size=18, weight='bold') header['relief'] = 'groove' header['padx'] = 8 header['fg'] = 'blue' header.grid(column=1, row=0, sticky='news') # Create empty list for labels and set a counter self.labels = [] i = 0 # Loop through the dict and assign to labels for key, value in self.weather.results.items(): if key != 'region' and key != 'img' and key != 'seven day': if key == 'current temperature': text = value.title() + '\u00b0' + ' F' else: text = value.title() self.labels.append([tk.Label(self.info_container, text=key.title(), anchor='w'), tk.Label(self.info_container, text=text, anchor='w')]) self.labels[i][0]['font'] = tkfont.Font(weight='bold', size=10) self.labels[i][0]['relief'] = 'groove' self.labels[i][1]['relief'] = 'groove' self.labels[i][0].grid(column=0, row=i, sticky='new', ipadx=5) self.labels[i][1].grid(column=1, row=i, sticky='new', ipadx=5) i += 1 # Create a header label for the extended forecast label = tk.Label(self.seven_day_container) label['text'] = 'Extended Forecast' label['font'] = tkfont.Font(weight='bold', size=14) label['bg'] = 'lightgray' label.grid(column=0, columnspan=len(self.weather.results['seven day']), row=0, sticky='new') # Create empty list to hold days self.days = [] i = 0 # Loop through the seven day forecast info for data in self.weather.results['seven day']: self.days.append(tk.Label(self.seven_day_container)) self.days[i]['compound'] = 'bottom' self.days[i]['text'] = f'{data["name"]}\n H: {data["high"]}\u00b0 F / L: {data["low"]}\u00b0 F' self.days[i]['font'] = tkfont.Font(weight='bold', size= 8) self.days[i]['image'] = self.get_image(data['image']['src']) self.days[i]['relief'] = 'groove' self.days[i].grid(column=i, row=1, sticky='new') i += 1 # Call self.update to update the information self.update() # function/method for getting and returning the image def get_image(self, src): url = 'https:' + src img = urllib.request.urlopen(url) raw = img.read() img.close() image = tk.PhotoImage(data=raw) image.img = image return image # Create the update function/method def update(self): self.img_label['image'] = self.get_image(self.weather.results['img']) i = 0 for key, value in self.weather.results.items(): if key != 'region' and key != 'img' and key != 'seven day': if key == 'current temperature': text = value.title() + '\u00b0' + ' F' else: text = value.title() self.labels[i-1][1]['text'] = text i += 1 i = 0 for img in self.weather.results['seven day']: self.days[i]['image'] = self.get_image(img['image']['src']) i += 1 self.info_container.after(300000, self.update) def main(): root = tk.Tk() root.title('Tkinter Weather App') root['padx'] = 5 root['pady'] = 4 root.resizable(False, False) Window(root) root.mainloop() main() |