Skip to content

Instantly share code, notes, and snippets.

@Surendrajat
Last active December 27, 2024 17:26
Show Gist options
  • Save Surendrajat/ff3876fd2166dd86fb71180f4e9342d7 to your computer and use it in GitHub Desktop.
Save Surendrajat/ff3876fd2166dd86fb71180f4e9342d7 to your computer and use it in GitHub Desktop.
A Clean & Customizable Weather module for Waybar
"custom/weather": {
"exec": "python ~/.config/waybar/scripts/weather.py",
"restart-interval": 300,
"return-type": "json",
"on-click": "xdg-open https://weather.com/en-IN/weather/today/l/$(location_id)"
// "format-alt": "{alt}",
},
#custom-weather.severe {
color: #eb937d;
}
#custom-weather.sunnyDay {
color: #c2ca76;
}
#custom-weather.clearNight {
color: #2b2b2a;
}
#custom-weather.cloudyFoggyDay, #custom-weather.cloudyFoggyNight {
color: #c2ddda;
}
#custom-weather.rainyDay, #custom-weather.rainyNight {
color: #5aaca5;
}
#custom-weather.showyIcyDay, #custom-weather.snowyIcyNight {
color: #d6e7e5;
}
#custom-weather.default {
color: #dbd9d8;
}
#!/usr/bin/env python
import subprocess
from pyquery import PyQuery # install using `pip install pyquery`
import json
# weather icons
weather_icons = {
"sunnyDay": "滛",
"clearNight": "望",
"cloudyFoggyDay": "",
"cloudyFoggyNight": "",
"rainyDay": "",
"rainyNight": "",
"snowyIcyDay": "",
"snowyIcyNight": "",
"severe": "",
"default": "",
}
# get location_id
# to get your own location_id, go to https://weather.com & search your location.
# once you choose your location, you can see the location_id in the URL(64 chars long hex string)
# like this: https://weather.com/en-IN/weather/today/l/c3e96d6cc4965fc54f88296b54449571c4107c73b9638c16aafc83575b4ddf2e
location_id = "c3e96d6cc4965fc54f88296b54449571c4107c73b9638c16aafc83575b4ddf2e" # TODO
# location_id = "8139363e05edb302e2d8be35101e400084eadcecdfce5507e77d832ac0fa57ae"
# priv_env_cmd = 'cat $PRIV_ENV_FILE | grep weather_location | cut -d "=" -f 2'
# location_id = subprocess.run(
# priv_env_cmd, shell=True, capture_output=True).stdout.decode('utf8').strip()
# get html page
url = "https://weather.com/en-IN/weather/today/l/" + location_id
html_data = PyQuery(url=url)
# current temperature
temp = html_data("span[data-testid='TemperatureValue']").eq(0).text()
# print(temp)
# current status phrase
status = html_data("div[data-testid='wxPhrase']").text()
status = f"{status[:16]}.." if len(status) > 17 else status
# print(status)
# status code
status_code = html_data("#regionHeader").attr("class").split(" ")[2].split("-")[2]
# print(status_code)
# status icon
icon = (
weather_icons[status_code]
if status_code in weather_icons
else weather_icons["default"]
)
# print(icon)
# temperature feels like
temp_feel = html_data(
"div[data-testid='FeelsLikeSection'] > span > span[data-testid='TemperatureValue']"
).text()
temp_feel_text = f"Feels like {temp_feel}c"
# print(temp_feel_text)
# min-max temperature
temp_min = (
html_data("div[data-testid='wxData'] > span[data-testid='TemperatureValue']")
.eq(0)
.text()
)
temp_max = (
html_data("div[data-testid='wxData'] > span[data-testid='TemperatureValue']")
.eq(1)
.text()
)
temp_min_max = f" {temp_min}\t\t {temp_max}"
# print(temp_min_max)
# wind speed
wind_speed = html_data("span[data-testid='Wind']").text().split("\n")[1]
wind_text = f"煮 {wind_speed}"
# print(wind_text)
# humidity
humidity = html_data("span[data-testid='PercentageValue']").text()
humidity_text = f" {humidity}"
# print(humidity_text)
# visibility
visbility = html_data("span[data-testid='VisibilityValue']").text()
visbility_text = f" {visbility}"
# print(visbility_text)
# air quality index
air_quality_index = html_data("text[data-testid='DonutChartValue']").text()
# print(air_quality_index)
# hourly rain prediction
prediction = html_data("section[aria-label='Hourly Forecast']")(
"div[data-testid='SegmentPrecipPercentage'] > span"
).text()
prediction = prediction.replace("Chance of Rain", "")
prediction = f"\n\n  (hourly) {prediction}" if len(prediction) > 0 else prediction
# print(prediction)
# tooltip text
tooltip_text = str.format(
"\t\t{}\t\t\n{}\n{}\n{}\n\n{}\n{}\n{}{}",
f'<span size="xx-large">{temp}</span>',
f"<big>{icon}</big>",
f"<big>{status}</big>",
f"<small>{temp_feel_text}</small>",
f"<big>{temp_min_max}</big>",
f"{wind_text}\t{humidity_text}",
f"{visbility_text}\tAQI {air_quality_index}",
f"<i>{prediction}</i>",
)
# print waybar module data
out_data = {
"text": f"{icon} {temp}",
"alt": status,
"tooltip": tooltip_text,
"class": status_code,
}
print(json.dumps(out_data))
@DoYouSeeAmin
Copy link

which font u use for weather icon

@Riddmaker
Copy link

I got an update on the fetching logic, also discussed further above.
The correct synthax is now

# get html page
url = "https://weather.com/en-IN/weather/today/l/" + location_id
html_data = PyQuery(url=url)

Updates on what args PyQuery takes can be found here: https://pyquery.readthedocs.io/en/latest/scrap.html (as also posted further above by @cn-danieldev.)

As of date of this comment I can confirm that this script still works!

@SeanEParsons
Copy link

Is it possible to get Fahrenheit? I notice there is no separate URL for Fahrenheit on the website, guess some JS handling or something.

Possible to get 5-day?

When I click the popup/dropdown thing, goes to 404 page: https://weather.com/en-IN/weather/today/l/

ie. missing location_id at that point.

To get English/Imperial units append '?units=e' to the end of your location_id. My locations looks like this:
location_id = "ff02642ddd763393bf9158589c1b4804cc84c808136cc42554efce2a92fc47fb?unit=e" # appending '?unit=e' changes everything to English/Imperial units
Here is what my screen looks like, yes I made a few other minor mods to the file since I don't know/understand any Asian characters.
20241226_11h18m47s_grim
I hope you, and others, find this helpful.

@SeanEParsons
Copy link

Hello, while I did write my own CSS for this, I did notice a typo in your CSS. In your CSS you have:
#custom-weather.showyIcyDay, #custom-weather.snowyIcyNight { color: #d6e7e5; }
It should say:
#custom-weather.snowyIcyDay, #custom-weather.snowyIcyNight { color: #d6e7e5; }
I noticed it when I started with your CSS sheet and wanted to have different appearances for Day and Night. By the way, I love the script and the lack of need to sign up for any additional APIs. It is simple, looks great, and it works.
weather

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment