103 lines
4.1 KiB
Python
103 lines
4.1 KiB
Python
import datetime
|
|
import json
|
|
import logging
|
|
from typing import Any
|
|
|
|
from bs4 import BeautifulSoup
|
|
|
|
from gallery.sketch.source import ApiSource
|
|
from gallery.sketch.weather.api import WeatherApi
|
|
from gallery.sketch.weather.model import Location, WeatherResponse, WeatherValue
|
|
|
|
from . import datehelp
|
|
from .parser import DAYS_PARSER, LOCATION_PARSER, ONE_DAY_PARSER, ROW_PARSERS
|
|
|
|
logger = logging.getLogger("gismeteo")
|
|
|
|
|
|
class GismeteoApi(WeatherApi):
|
|
PROVIDER = "gismeteo"
|
|
SOURCE = ApiSource(
|
|
"https://www.gismeteo.ru",
|
|
cookies={
|
|
"cf_clearance": (
|
|
"zPj8qeaYZWp5BUZsWIRD7kd32s59IDWWaVvD7GGf6b4-1724254262-1.2.1.1-"
|
|
"R1PaHoqlm4OEgHfrOg6oAJmVmFJ7053JI_QDjIFlCAmbNY0oyw1J4QtgmEkAkTWF4C99X5hpXmZB2en."
|
|
"9Ey3NL0kzaE10UGBHPli5OLxHNKC3wQ34xmxTxg6GcKouXOPRgqo92lVRpQP7ghvDmvvT_"
|
|
"S6YXDbRonkamptWhZiAsIhsnIQg2Mt7Lk1fxSEVbaey_RXVQBvaR2ofiFgIavcbQPRFSvJ."
|
|
"Ct_FujmymTAZWh1XHTptK32kur81NXyPuARThetOKQm8AklaMa855Oom6Bms1a4F9b0yEHSd2inA4j3FR7uauu8hhwO0Z2goa3."
|
|
"ktpXXAQLz6dm.fBEWIHD7wooda15X57tCcDOely4hxhO4LK2lIH6TbOr."
|
|
"rZQAiRRhltHiCizP1Ou2SiF_81lb1umoDh739tQD1cnw_USnL."
|
|
"JwTHvkB00ZnaHRMi4FCBrsKIE0NxJO6kiv1QANqumzf5.8_pSIGRo2cKeO8xCydduDNFbStdOmLR6FU7ZKqVu"
|
|
)
|
|
},
|
|
)
|
|
|
|
def _parse_oneday(self, date: datetime.date, data: str) -> WeatherResponse:
|
|
result: list[dict[str, Any]] = []
|
|
soup = BeautifulSoup(data, features="html.parser")
|
|
location = LOCATION_PARSER.parse_location(data)
|
|
widget = ONE_DAY_PARSER.parse_widget(soup)
|
|
for parser in ROW_PARSERS:
|
|
for index, value in enumerate(parser.parse_row(widget)):
|
|
while len(result) < index + 1:
|
|
result.append({})
|
|
result[index][parser.KEY] = value
|
|
values = [WeatherValue(**item) for item in result]
|
|
return WeatherResponse(
|
|
location=location or "n/a",
|
|
date=date,
|
|
period="day",
|
|
values=values,
|
|
)
|
|
|
|
def _parse_manydays(self, data: str) -> WeatherResponse:
|
|
result: list[dict[str, Any]] = []
|
|
soup = BeautifulSoup(data, features="html.parser")
|
|
location = LOCATION_PARSER.parse_location(data)
|
|
widget = DAYS_PARSER.parse_widget(soup)
|
|
for parser in ROW_PARSERS:
|
|
for index, value in enumerate(parser.parse_row(widget)):
|
|
while len(result) < index + 1:
|
|
result.append({})
|
|
result[index][parser.KEY] = value
|
|
values = [WeatherValue(**item) for item in result]
|
|
return WeatherResponse(
|
|
location=location or "n/a",
|
|
date=datetime.date.today(),
|
|
period="days",
|
|
values=values,
|
|
)
|
|
|
|
async def find_locations(self, query: str) -> list[Location]:
|
|
geo = "ru"
|
|
latitude = 52.968498
|
|
longitude = 36.0695
|
|
data = json.loads(
|
|
await self.SOURCE.request(
|
|
f"mq/city/q/?q={query}&geo={geo}&latitude={latitude}&longitude={longitude}&limit=10"
|
|
)
|
|
)
|
|
result = []
|
|
for item in data["data"]:
|
|
result.append(
|
|
Location(
|
|
id=f"{item['slug']}-{item['id']}",
|
|
name=item["translations"]["kk"]["city"]["name"],
|
|
lat=item["coordinates"]["latitude"],
|
|
lon=item["coordinates"]["longitude"],
|
|
country=item["translations"]["kk"]["country"]["name"],
|
|
district=item["translations"]["kk"]["district"]["name"],
|
|
subdistrict=item["translations"]["kk"]["subdistrict"]["name"],
|
|
)
|
|
)
|
|
return result
|
|
|
|
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
|
|
data = await self.SOURCE.request(f"weather-{location_id}/{datehelp.dump(date)}")
|
|
return self._parse_oneday(date, data)
|
|
|
|
async def get_days(self, location_id: str, days: int) -> WeatherResponse:
|
|
data = await self.SOURCE.request(f"weather-{location_id}/{days}-days")
|
|
return self._parse_manydays(data)
|