fix(gismeteo): fix gismeteo parser

This commit is contained in:
2026-08-28 10:02:36 +03:00
parent 50c4221b8d
commit 60c0a7a6fc
5 changed files with 35 additions and 17 deletions
+17 -11
View File
@@ -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
+1 -1
View File
@@ -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))
+10
View File
@@ -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
+5 -1
View File
@@ -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] = {
+2 -4
View File
@@ -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