92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
import logging
|
|
from enum import Enum
|
|
|
|
import dateparser
|
|
from bs4 import Tag
|
|
|
|
from gallery.sketch.weather.model import Cloudness, Precipitation, Sky, WeatherResponse
|
|
from gallery.sketch.weather.parser import ParseError, parse_wind_direction
|
|
from gallery.sketch.weather.util import build_weather_value
|
|
|
|
logger = logging.getLogger("yandexweather")
|
|
|
|
|
|
class DayPart(Enum):
|
|
MORNING = ("Утром", 6)
|
|
AFTERNOON = ("Днём", 12)
|
|
EVENING = ("Вечером", 18)
|
|
NIGHT = ("Ночью", 0)
|
|
|
|
def __init__(self, title: str, hour: int):
|
|
super().__init__()
|
|
self.title = title
|
|
self.hour = hour
|
|
|
|
|
|
def parse_sky(sky: str) -> Sky:
|
|
cloudness = Cloudness.CLEAR
|
|
precipitation = Precipitation.NO
|
|
thunder = False
|
|
fog = False
|
|
if sky == "ясно":
|
|
pass
|
|
elif sky == "облачно с прояснениями":
|
|
cloudness = Cloudness.PARTLY_CLOUDY
|
|
elif sky == "малооблачно":
|
|
cloudness = Cloudness.CLOUDY
|
|
elif sky == "пасмурно":
|
|
cloudness = Cloudness.MAINLY_CLOUDY
|
|
elif sky == "небольшой дождь":
|
|
precipitation = Precipitation.SMALL_RAIN
|
|
elif sky == "дождь":
|
|
precipitation = Precipitation.RAIN
|
|
elif sky == "ливень":
|
|
precipitation = Precipitation.SHOWER
|
|
else:
|
|
logger.warning("unknown sky value: %s", sky)
|
|
return Sky(
|
|
cloudness=cloudness,
|
|
precipitation=precipitation,
|
|
thunder=thunder,
|
|
fog=fog,
|
|
)
|
|
|
|
|
|
def parse_article(article: Tag, location: str) -> WeatherResponse:
|
|
date_str = article.select_one("[class^=AppForecastDayHeader_dayTitle]").text.split(",")[-1].strip()
|
|
date = dateparser.parse(date_str, languages=["ru"])
|
|
if date is None:
|
|
raise ParseError.invalid_date(date_str)
|
|
values = []
|
|
for day_part in DayPart:
|
|
value = build_weather_value(date.replace(hour=day_part.hour))
|
|
day_part_tag = article.find(string=day_part.title)
|
|
temperature_tag = day_part_tag.next_element
|
|
temperature = int(temperature_tag.text.strip().rstrip("°"))
|
|
value.temperature.append(temperature)
|
|
sky_tag = temperature_tag.next_element.next_element.next_element
|
|
sky_str = sky_tag.text.strip()
|
|
value.sky = parse_sky(sky_str)
|
|
temperature_tag = sky_tag.next_element.next_element
|
|
temperature = int(temperature_tag.text.strip().rstrip("°"))
|
|
value.temperature.append(temperature)
|
|
wind_speed_tag = temperature_tag.next_element.next_element
|
|
wind_speed = int(wind_speed_tag.text.strip())
|
|
value.wind_speed = wind_speed
|
|
wind_direction_tag = wind_speed_tag.next_element.next_element.next_element.next_element
|
|
wind_direction_str = wind_direction_tag.text.strip()
|
|
value.wind_direction = parse_wind_direction(wind_direction_str)
|
|
humidity_tag = wind_direction_tag.next_element.next_element.next_element.next_element
|
|
humidity = int(humidity_tag.text.strip().rstrip("%"))
|
|
value.humidity = humidity
|
|
pressure_tag = humidity_tag.next_element.next_element
|
|
pressure = int(pressure_tag.text.strip())
|
|
value.pressure.append(pressure)
|
|
values.append(value)
|
|
return WeatherResponse(
|
|
location=location,
|
|
date=date,
|
|
period="day",
|
|
values=values,
|
|
)
|