fix(gismeteo): fix gismeteo parser
This commit is contained in:
@@ -12,7 +12,7 @@ from gallery.sketch.weather.model import (
|
|||||||
Sky,
|
Sky,
|
||||||
WindDirection,
|
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
|
from .core import BaseWidgetParser, RowParser
|
||||||
|
|
||||||
@@ -46,9 +46,15 @@ class DateParser(RowParser[datetime.datetime]):
|
|||||||
time = datetime.datetime.fromtimestamp(timestamp)
|
time = datetime.datetime.fromtimestamp(timestamp)
|
||||||
yield time
|
yield time
|
||||||
else:
|
else:
|
||||||
|
month = None
|
||||||
for item in tag.select(".widget-row.widget-row-date > .row-item"):
|
for item in tag.select(".widget-row.widget-row-date > .row-item"):
|
||||||
date_str = item.text
|
date_str = item.text
|
||||||
date = dateparser.parse(date_str, languages=["ru"])
|
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
|
yield date
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +71,7 @@ class SkyParser(RowParser[Sky]):
|
|||||||
|
|
||||||
PRECIPITATION_MAP: dict[str, Precipitation] = {
|
PRECIPITATION_MAP: dict[str, Precipitation] = {
|
||||||
"без осадков": Precipitation.NO,
|
"без осадков": Precipitation.NO,
|
||||||
|
"без существенных осадков": Precipitation.NO,
|
||||||
"небольшой дождь": Precipitation.SMALL_RAIN,
|
"небольшой дождь": Precipitation.SMALL_RAIN,
|
||||||
"сильный дождь": Precipitation.HEAVY_RAIN,
|
"сильный дождь": Precipitation.HEAVY_RAIN,
|
||||||
"очень сильный дождь": Precipitation.HEAVY_RAIN,
|
"очень сильный дождь": Precipitation.HEAVY_RAIN,
|
||||||
@@ -82,8 +89,13 @@ class SkyParser(RowParser[Sky]):
|
|||||||
"град": Precipitation.HAIL,
|
"град": Precipitation.HAIL,
|
||||||
}
|
}
|
||||||
|
|
||||||
THUNDER = "гроза"
|
THUNDER = {"гроза"}
|
||||||
FOG = "дымка"
|
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]:
|
def parse_row(self, tag: Tag) -> Iterable[Sky]:
|
||||||
for item in tag.select(".widget-row[data-row=icon-tooltip] > .row-item"):
|
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(",")}
|
values = {item.strip().lower() for item in sky_str.split(",")}
|
||||||
cloudness = Cloudness.CLEAR
|
cloudness = Cloudness.CLEAR
|
||||||
precipitation = Precipitation.NO
|
precipitation = Precipitation.NO
|
||||||
thunder = False
|
values, thunder = self._detect_flag(values, self.THUNDER)
|
||||||
fog = False
|
values, fog = self._detect_flag(values, self.FOG)
|
||||||
if self.THUNDER in values:
|
|
||||||
thunder = True
|
|
||||||
values.remove(self.THUNDER)
|
|
||||||
if self.FOG in values:
|
|
||||||
fog = True
|
|
||||||
values.remove(self.FOG)
|
|
||||||
for k, v in self.CLOUDNESS_MAP.items():
|
for k, v in self.CLOUDNESS_MAP.items():
|
||||||
if k in values:
|
if k in values:
|
||||||
cloudness = v
|
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_str = article.select_one("[class^=AppForecastDayHeader_dayTitle]").text.split(",")[-1].strip()
|
||||||
date = dateparser.parse(date_str, languages=["ru"])
|
date = dateparser.parse(date_str, languages=["ru"])
|
||||||
if date is None:
|
if date is None:
|
||||||
raise ParseError("Invalid date string", date_str)
|
raise ParseError.invalid_date(date_str)
|
||||||
values = []
|
values = []
|
||||||
for day_part in DayPart:
|
for day_part in DayPart:
|
||||||
value = build_weather_value(date.replace(hour=day_part.hour))
|
value = build_weather_value(date.replace(hour=day_part.hour))
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ class Cloudness(StrEnum):
|
|||||||
CLOUDY = auto()
|
CLOUDY = auto()
|
||||||
MAINLY_CLOUDY = auto()
|
MAINLY_CLOUDY = auto()
|
||||||
|
|
||||||
|
values: list[Self]
|
||||||
|
|
||||||
|
|
||||||
|
Cloudness.values = list(Cloudness)
|
||||||
|
|
||||||
|
|
||||||
class Precipitation(StrEnum):
|
class Precipitation(StrEnum):
|
||||||
NO = auto()
|
NO = auto()
|
||||||
@@ -39,6 +44,11 @@ class Precipitation(StrEnum):
|
|||||||
HEAVY_SNOW = auto()
|
HEAVY_SNOW = auto()
|
||||||
HAIL = auto()
|
HAIL = auto()
|
||||||
|
|
||||||
|
values: list[Self]
|
||||||
|
|
||||||
|
|
||||||
|
Precipitation.values = list(Precipitation)
|
||||||
|
|
||||||
|
|
||||||
class Sky(Model):
|
class Sky(Model):
|
||||||
cloudness: Cloudness
|
cloudness: Cloudness
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
from typing import Self
|
||||||
|
|
||||||
from gallery.sketch.weather.model import WindDirection, WindDirectionDeg
|
from gallery.sketch.weather.model import WindDirection, WindDirectionDeg
|
||||||
|
|
||||||
|
|
||||||
class ParseError(Exception):
|
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] = {
|
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_speed = round(statistics.mean(wind_speeds))
|
||||||
result.wind_gust = round(statistics.mean(wind_gusts))
|
result.wind_gust = round(statistics.mean(wind_gusts))
|
||||||
result.wind_direction = statistics.mean(wind_directions)
|
result.wind_direction = statistics.mean(wind_directions)
|
||||||
# TODO: merge cloudnesses
|
|
||||||
for item in cloudnesses:
|
for item in cloudnesses:
|
||||||
if item != Cloudness.CLEAR:
|
if Cloudness.values.index(item) > Cloudness.values.index(result.sky.cloudness):
|
||||||
result.sky.cloudness = item
|
result.sky.cloudness = item
|
||||||
# TODO: merge precipitations
|
|
||||||
for item in 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.sky.precipitation = item
|
||||||
result.precipitation = precipitation
|
result.precipitation = precipitation
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user