fix(gismeteo): fix gismeteo parser
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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] = {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user