From 60c0a7a6fcede394cabc5aad4f1242bb601f0ae4 Mon Sep 17 00:00:00 2001 From: shmyga Date: Fri, 28 Aug 2026 10:02:36 +0300 Subject: [PATCH] fix(gismeteo): fix gismeteo parser --- gallery/painting/gismeteo/parser.py | 28 ++++++++++++++---------- gallery/painting/yandexweather/parser.py | 2 +- gallery/sketch/weather/model.py | 10 +++++++++ gallery/sketch/weather/parser.py | 6 ++++- gallery/sketch/weather/util.py | 6 ++--- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/gallery/painting/gismeteo/parser.py b/gallery/painting/gismeteo/parser.py index 28c31dd..017da50 100644 --- a/gallery/painting/gismeteo/parser.py +++ b/gallery/painting/gismeteo/parser.py @@ -12,7 +12,7 @@ from gallery.sketch.weather.model import ( Sky, WindDirection, ) -from gallery.sketch.weather.parser import parse_wind_direction +from gallery.sketch.weather.parser import ParseError, parse_wind_direction from .core import BaseWidgetParser, RowParser @@ -46,9 +46,15 @@ class DateParser(RowParser[datetime.datetime]): time = datetime.datetime.fromtimestamp(timestamp) yield time else: + month = None for item in tag.select(".widget-row.widget-row-date > .row-item"): date_str = item.text date = dateparser.parse(date_str, languages=["ru"]) + if date is None: + raise ParseError.invalid_date(date_str) + if month and month > date.month: + date = date.replace(month=month) + month = date.month yield date @@ -65,6 +71,7 @@ class SkyParser(RowParser[Sky]): PRECIPITATION_MAP: dict[str, Precipitation] = { "без осадков": Precipitation.NO, + "без существенных осадков": Precipitation.NO, "небольшой дождь": Precipitation.SMALL_RAIN, "сильный дождь": Precipitation.HEAVY_RAIN, "очень сильный дождь": Precipitation.HEAVY_RAIN, @@ -82,8 +89,13 @@ class SkyParser(RowParser[Sky]): "град": Precipitation.HAIL, } - THUNDER = "гроза" - FOG = "дымка" + THUNDER = {"гроза"} + FOG = {"дымка", "туман"} + + @classmethod + def _detect_flag(cls, values: set[str], flag_values: set[str]) -> tuple[set[str], bool]: + result_values = values - flag_values + return result_values, len(result_values) < len(values) def parse_row(self, tag: Tag) -> Iterable[Sky]: for item in tag.select(".widget-row[data-row=icon-tooltip] > .row-item"): @@ -91,14 +103,8 @@ class SkyParser(RowParser[Sky]): values = {item.strip().lower() for item in sky_str.split(",")} cloudness = Cloudness.CLEAR precipitation = Precipitation.NO - thunder = False - fog = False - if self.THUNDER in values: - thunder = True - values.remove(self.THUNDER) - if self.FOG in values: - fog = True - values.remove(self.FOG) + values, thunder = self._detect_flag(values, self.THUNDER) + values, fog = self._detect_flag(values, self.FOG) for k, v in self.CLOUDNESS_MAP.items(): if k in values: cloudness = v diff --git a/gallery/painting/yandexweather/parser.py b/gallery/painting/yandexweather/parser.py index 27f0720..15dd479 100644 --- a/gallery/painting/yandexweather/parser.py +++ b/gallery/painting/yandexweather/parser.py @@ -54,7 +54,7 @@ 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 string", date_str) + raise ParseError.invalid_date(date_str) values = [] for day_part in DayPart: value = build_weather_value(date.replace(hour=day_part.hour)) diff --git a/gallery/sketch/weather/model.py b/gallery/sketch/weather/model.py index 08d05fb..59dc7a9 100644 --- a/gallery/sketch/weather/model.py +++ b/gallery/sketch/weather/model.py @@ -28,6 +28,11 @@ class Cloudness(StrEnum): CLOUDY = auto() MAINLY_CLOUDY = auto() + values: list[Self] + + +Cloudness.values = list(Cloudness) + class Precipitation(StrEnum): NO = auto() @@ -39,6 +44,11 @@ class Precipitation(StrEnum): HEAVY_SNOW = auto() HAIL = auto() + values: list[Self] + + +Precipitation.values = list(Precipitation) + class Sky(Model): cloudness: Cloudness diff --git a/gallery/sketch/weather/parser.py b/gallery/sketch/weather/parser.py index 3b601df..708915e 100644 --- a/gallery/sketch/weather/parser.py +++ b/gallery/sketch/weather/parser.py @@ -1,8 +1,12 @@ +from typing import Self + from gallery.sketch.weather.model import WindDirection, WindDirectionDeg class ParseError(Exception): - pass + @classmethod + def invalid_date(cls, date_str: str) -> Self: + return cls("Invalid date string", date_str) WIND_DIRECTION_MAP: dict[str, WindDirection] = { diff --git a/gallery/sketch/weather/util.py b/gallery/sketch/weather/util.py index 43afbc3..9c5f374 100644 --- a/gallery/sketch/weather/util.py +++ b/gallery/sketch/weather/util.py @@ -50,13 +50,11 @@ def merge_weather_values(date: datetime.datetime, values: list[WeatherValue]) -> result.wind_speed = round(statistics.mean(wind_speeds)) result.wind_gust = round(statistics.mean(wind_gusts)) result.wind_direction = statistics.mean(wind_directions) - # TODO: merge cloudnesses for item in cloudnesses: - if item != Cloudness.CLEAR: + if Cloudness.values.index(item) > Cloudness.values.index(result.sky.cloudness): result.sky.cloudness = item - # TODO: merge precipitations for item in precipitations: - if item != Precipitation.NO: + if Precipitation.values.index(item) > Precipitation.values.index(result.sky.precipitation): result.sky.precipitation = item result.precipitation = precipitation return result