46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
import datetime
|
|
from typing import Any, Dict, List
|
|
|
|
import aiohttp
|
|
from bs4 import BeautifulSoup
|
|
|
|
from weather.api import WeatherApi
|
|
from weather.model import WeatherResponse, WeatherValue
|
|
|
|
from . import datehelp
|
|
from .location import LOCATION_BUNDLE
|
|
from .parser import LOCATION_PARSER, ONE_DAY_PARSER, ROW_PARSERS
|
|
|
|
|
|
class GismeteoApi(WeatherApi):
|
|
BASE_URL = "https://www.gismeteo.ru"
|
|
|
|
async def _request(self, endpoint: str) -> str:
|
|
url = f"{self.BASE_URL}/{endpoint}"
|
|
async with aiohttp.ClientSession(raise_for_status=True) as session:
|
|
async with session.request("GET", url) as response:
|
|
return await response.text()
|
|
|
|
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,
|
|
)
|
|
|
|
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
|
|
location = LOCATION_BUNDLE.parse(location_id)
|
|
data = await self._request(f"weather-{location}/{datehelp.dump(date)}")
|
|
return self._parse_oneday(date, data)
|