Severe weather alerts with a simple Python script

If like many you have been starting gardens and planting rather than traveling and visiting in recent months, there is one important thing to consider lately – severe weather reports including frost on your crops. I noted there was a little red (!) alert icon on an Android weather widget, but there seems to be no such alert for desktop computer or Linux computer or phone. It is a fairly simple to make this alert though with a simple script:

Prep: Install lxml and requests libraries, these are a bit better and easier than the built in xml and libraries:

pip3 install lxml
pip3 install requests

You will need to find the ATOM feed url the national weather service gives for your region. The regions are listed mid-page here: https://alerts.weather.gov/ – for Iowa for example that would be the ATOM link, https://alerts.weather.gov/cap/ia.php?x=0.

Read a url to a string with:

req = requests.get('https://alerts.weather.gov/cap/wwaatmget.php?x=ORC029&y=0')
    print(dir(req))

This shows the output, various attributes of which the “content” is mostly what we want:

import requests
import lxml

def main(args):
    req = requests.get('https://alerts.weather.gov/cap/wwaatmget.php?x=ORC029&y=0')
    print(dir(req))
    print(req.content)
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Gives the content of an ATOM xml. Now to change that inner script to parse it with lxml:

    req = requests.get('https://alerts.weather.gov/cap/wwaatmget.php?x=ORC029&y=0')
    xml = req.content
    from lxml import etree
    atom = etree.fromstring(xml)
    print(atom)

This creates an element tree object:

$ python3 ./nws.py 
<Element {http://www.w3.org/2005/Atom}feed ...

Note the namespace, a namespace is a space where a certain name has meaning (for example the word “can” as a verb or “can” as a container, you could say are in different namespaces, namespace of verbs and namespace of containers. All the elements in this document are atom xml elements… not svg graphics, not some other xml… and you can find an example of getting an element or elements here. Xpath is a good way to get all elements (by “//tagname” or a certain path such as “/outer/inner/tag/in/tag…” with outer tag and inner tag directly inside it.

The notifications area (at the top center of the screen or the side on older Ubuntu systems) can be notified by adding a notification using something like the examples here. I used libnotify, and pulling this all together:

import requests
import lxml

from gi.repository import Notify
Notify.init("weatheralert")

def main(args):
    req = requests.get('https://alerts.weather.gov/cap/or.php?x=0')
    xml = req.content
    from lxml import etree
    ns = {'atom': 'http://www.w3.org/2005/Atom'}
    atom = etree.fromstring(xml)
    for element in atom.xpath('//atom:entry', namespaces=ns):
        title = ''
        text = ''
        for node in element.iterchildren():
            if node.tag.find("event") >-1:
                title = node.text
            elif node.tag.find("summary") >-1:
                text = node.text
        notification = Notify.Notification.new(title, text)
        notification.show()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

After some adjustments to not show non-alerts, the current revision is available here:
https://github.com/programmin1/WeatherAlert

Check it out add it to your crontab to get it set… run:

sudo nano /etc/crontab

The script can be run once every couple hours by adding a line:

 1 */2  * * *   username    python3 /home/user/path/to/file.py

Leave a Reply

Your email address will not be published. Required fields are marked *

4 × seven =