Worldwide Weather Forecast Web App - Starting a New Business - Part 8
Introduction
Let's build a web app to forecast weather anywhere around the world. Our app will take a city name and you will return the 5-day forecast in icons! If you follow the video and use PythonAnywere, you will be able to use it on your mobile phone.
Code
from IPython.display import Image
Image(filename='viralml-book.png', width=600)
Starting a Business? Part 8
Let's build a simple weather forecasting web application using the MVP Light Stack!
Image(filename='five-day-forecast-web-app.png', width=500)
Starting a Business? Part 8
Let's build a simple weather forecasting web application using the MVP Light Stack!
You will need two free accounts to follow this walkthrough:
- PythonAnywhere.com
- OpenWeatherMap.org
Signup for a "Free" account at OpenWeatherMap (https://openweathermap.org/price) and create an API key to follow along.
Singup for a "Beginner Free" account at PythonAnywhere (https://www.pythonanywhere.com/pricing/).
Once you have both accounts confirmed, you are ready to follow along and create a simple weather forecasting tool that anybody around the world can use!!
YOUR_OPENWEATHERMAP_API_KEY = 'ADD-YOUR-API-KEY-HERE'
Weather rest API function call¶
# bring in real weather data using openweathermap and json.load
from urllib.request import urlopen
import json
weather_json = json.load(
urlopen("http://api.openweathermap.org/data/2.5/weather?q=Barcelona&appid=" + YOUR_OPENWEATHERMAP_API_KEY))
weather_json
Forecast rest API function call¶
selected_location = "Seattle"
openweathermap_url = "http://api.openweathermap.org/data/2.5/forecast?q=" + selected_location + "&APPID=" + YOUR_OPENWEATHERMAP_API_KEY
weather_forecast_json = json.load(urlopen(openweathermap_url))
weather_forecast_json
# https://openweathermap.org/api
[w['dt_txt'] for w in weather_forecast_json['list']]
len([w['dt_txt'] for w in weather_forecast_json['list']])
Pull weather icons¶
### Pull weather icons
for w in weather_forecast_json['list']:
print(w['dt_txt'])
print(w['weather'])
print(w['weather'][0]['icon'])
from IPython.core.display import Image, display
import time
for w in weather_forecast_json['list']:
# slow it down, be courteous
time.sleep(0.1)
print(w['dt_txt'])
outlook_icon = w['weather'][0]['icon'] + ".png"
display(Image("http://openweathermap.org/img/w/" + outlook_icon, unconfined=True))
Let's fix the time to be in the local time zone of the forecast and not UTC¶
First call the weather function for your location to get the offset in seconds then use that offset on the OpenWeatherMap provided UTC time.
location = 'seattle'
weather_json = json.load(
urlopen("http://api.openweathermap.org/data/2.5/weather?q=" + location + "&appid=" + YOUR_OPENWEATHERMAP_API_KEY))
weather_json
tz_offset = float(weather_json['timezone'])
print(tz_offset)
import datetime
date_str = '2019-10-01 15:00:00'
datetime_object = datetime.datetime.strptime (date_str, '%Y-%m-%d %H:%M:%S')
datetime_object + datetime.timedelta(seconds=tz_offset)
from IPython.core.display import Image, display
import time
for w in weather_forecast_json['list']:
# slow it down, be courteous
time.sleep(0.1)
date_str = w['dt_txt']
print('UTC:', date_str)
datetime_object = datetime.datetime.strptime (date_str, '%Y-%m-%d %H:%M:%S')
datetime_object = datetime_object + datetime.timedelta(seconds=tz_offset)
print('Local time in', location.capitalize(), str(datetime_object))
outlook_icon = w['weather'][0]['icon'] + ".png"
display(Image("http://openweathermap.org/img/w/" + outlook_icon, unconfined=True))
break;
Let's Build Our Flask Application!¶
Inputing a location. OK, this is a bit of a hack but will simplify our implemenation tremendously. We will use the URl get input method. This means you will need to call your weather forecasting app the following way:
http://<<YOUR_PYTHONANYWHERE_ACCOUNT_NAME>>.pythonanywhere.com/?l=London
A word on encoding and decoding text when passing them through URL address links:
# Making text Internet/URL friendly
import urllib.parse
rez = urllib.parse.quote_plus('New York')
rez
str(urllib.parse.unquote_plus(rez)).title()
def forecaster():
message = "Sorry, I cannot find that location..."
if request.method == 'GET':
selected_location = request.args.get('l')
# deal with spaces and special characters
selected_location = urllib.parse.quote_plus(selected_location)
openweathermap_url = "https://api.openweathermap.org/data/2.5/weather?q=" + selected_location + "&mode=json&APPID=" + YOUR_OPENWEATHERMAP_API_KEY
# call the openweathermap api
weather_json = []
try:
weather_json = requests.get(openweathermap_url).json()
except:
# couldn't find location
e = sys.exc_info()[0]
if (len(weather_json) > 3):
message = ''
tz_offset = float(weather_json['timezone'])
openweathermap_url = "http://api.openweathermap.org/data/2.5/forecast?q=" + selected_location + "&mode=json&APPID=" + YOUR_OPENWEATHERMAP_API_KEY
weather_forecast_json = json.load(urlopen(openweathermap_url))
message = '<HTML><BODY><H1>5 Day / 3 Hour Forecast For ' + str(urllib.parse.unquote_plus(selected_location)).title() + '</H1><BR><BR>'
for w in weather_forecast_json['list']:
# slow it down, be courteous
time.sleep(0.1)
# get local time
date_str = w['dt_txt']
datetime_object = datetime.datetime.strptime (date_str, '%Y-%m-%d %H:%M:%S')
datetime_object = datetime_object + datetime.timedelta(seconds=tz_offset)
message += str(datetime_object) + '<BR>'
outlook_icon = w['weather'][0]['icon'] + ".png"
message += "<img src='http://openweathermap.org/img/w/" + outlook_icon + "' /><BR><BR>"
message += '</BODY></HTML>'
Get A PythonAnywhere Account - It's Free¶
Sign up for a free account on PythonAnywhere.com - no credit cards required, only a valid email address.
Setting Up Flask Web Framework¶
Next, let's setup a Flask web-serving platform. It is super easy to do. Under the 'Web' tab, click the 'Add a new web app' blue button. And accept the defaults until you get to the 'Select a Python Web framework' and click on 'Flask' and then the latest Python framework.
Full flask implementation:¶
from flask import Flask, Markup, request
import datetime, time, json, sys, requests
from urllib.request import urlopen
import urllib.parse
YOUR_OPENWEATHERMAP_API_KEY = '4d87794afdcfe073ca9d7fc4c5da86e3'
app = Flask(__name__)
@app.route("/", methods=['GET'])
def forecaster():
message = "Sorry, I cannot find that location..."
if request.method == 'GET':
selected_location = request.args.get('l')
if selected_location is not None:
# deal with spaces and special characters
selected_location = urllib.parse.quote_plus(selected_location)
openweathermap_url = "https://api.openweathermap.org/data/2.5/weather?q=" + selected_location + "&mode=json&APPID=" + YOUR_OPENWEATHERMAP_API_KEY
# call the openweathermap api
weather_json = []
try:
weather_json = requests.get(openweathermap_url).json()
except:
# couldn't find location
e = sys.exc_info()[0]
if (len(weather_json) > 3):
message = ''
tz_offset = float(weather_json['timezone'])
openweathermap_url = "http://api.openweathermap.org/data/2.5/forecast?q=" + selected_location + "&mode=json&APPID=" + YOUR_OPENWEATHERMAP_API_KEY
weather_forecast_json = json.load(urlopen(openweathermap_url))
message = '<HTML><BODY><H1>5 Day / 3 Hour Forecast For ' + str(urllib.parse.unquote_plus(selected_location)).title() + '</H1><BR><BR>'
for w in weather_forecast_json['list']:
# slow it down, be courteous
time.sleep(0.1)
# get local time
date_str = w['dt_txt']
datetime_object = datetime.datetime.strptime (date_str, '%Y-%m-%d %H:%M:%S')
datetime_object = datetime_object + datetime.timedelta(seconds=tz_offset)
message += str(datetime_object) + '<BR>'
outlook_icon = w['weather'][0]['icon'] + ".png"
message += "<img src='http://openweathermap.org/img/w/" + outlook_icon + "' /><BR><BR>"
message += '</BODY></HTML>'
# tell Flask to interpret HTML tags as actual HTML
message = Markup(message)
return message
Show Notes
(pardon typos and formatting -these are the notes I use to make the videos)
Let's build a web app to forecast weather anywhere around the world. Our app will take a city name and you will return the 5-day forecast in icons! If you follow the video and use PythonAnywere, you will be able to use it on your mobile phone.