Scraping AccuWeather's minute-by-minute rain forecast
AccuWeather has a page called MinuteCast that tries to tell you, a minute at a time, whether it’s about to rain on you in the next couple of hours. That’s exactly what I want: something glanceable that tells me whether to grab an umbrella before I head out for a walk. AccuWeather does sell an API, but the cheapest plan is $25 a month, and I’m not even sure that includes MinuteCast. That was out of the question for an umbrella reminder, so one Sunday evening I opened a notebook and went scraping.
I didn’t start from scratch. Home Assistant publishes a Jupyter notebook that walks you through web scraping with requests and BeautifulSoup, as a warm-up for its scrape sensor. I swapped its example URL for the MinuteCast page for our area, and set a browser-ish User-Agent header so the request looked like it came from a person.
Then it was a matter of poking at the HTML with CSS selectors until the right bits fell out:
.current-summary .summarygives the headline, which on the evening I tried it was a smug “No precipitation for at least 120 min”..current-tempgives the temperature (15° that evening)..realfeel-tempgives AccuWeather’s “RealFeel”, once you chop the label off the front of the text (14°, so a bit nippy)..minute-innergives the good stuff: one block per minute, each with a time, an icon and a phrase. The page actually lists four hours of them: 240 blocks, from 7:01 pm to 11:00 pm, every one of which said “No Precipitation”. A thrilling first dataset, but at least it was consistent.
The icons are numbered SVGs, so the last thing I did was loop over numbers 1 to 49 and draw them all in the notebook, to see what the full set looks like. A few numbers don’t exist at all (9, 10, 27, 28, and everything from 45 up), so the set is a bit gappy.
Home Assistant’s notebook ends with a few cells that send the scraped value to Home Assistant as a sensor. I never changed those to send the rain forecast, and I didn’t need to. The notebook’s real job was finding the right selector, and once I had that, Home Assistant’s own scrape sensor could do the rest:
sensor:
- platform: scrape
name: Current Weather
resource: "https://www.accuweather.com/en/gb/<your-town>/<postcode>/minute-weather-forecast/<location-id>"
headers:
User-Agent: "Mozilla/5.0 (X11; Linux x86_64)"
select: ".current-summary .summary"
value_template: '{{ value.strip() }}'
scan_interval: 300
Every five minutes it fetches the page, pulls out the headline, and trims the whitespace off it. So now Home Assistant has a sensor that says, in plain English, whether it’s going to rain in the next couple of hours: just the glance I wanted before heading out.
scrape:
- resource: "https://www.accuweather.com/en/gb/<your-town>/<postcode>/minute-weather-forecast/<location-id>"
headers:
User-Agent: "Mozilla/5.0 (X11; Linux x86_64)"
scan_interval: 300
sensor:
name: Current Weather
unique_id: rainsummary
select: ".current-summary .summary"
value_template: '{{ value.strip() }}'