feat(api): add ApiSource

This commit is contained in:
2024-08-21 19:42:53 +03:00
parent b3043c3c8c
commit 0638fb8d50
3 changed files with 61 additions and 49 deletions

View File

@@ -2,10 +2,10 @@ import datetime
import logging import logging
from typing import Any, Dict, List from typing import Any, Dict, List
import aiohttp
from aiocache import cached from aiocache import cached
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from gallery.sketch.source import ApiSource
from gallery.sketch.weather.api import WeatherApi from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.catalog import LocationId from gallery.sketch.weather.catalog import LocationId
from gallery.sketch.weather.model import WeatherResponse, WeatherValue from gallery.sketch.weather.model import WeatherResponse, WeatherValue
@@ -17,32 +17,22 @@ logger = logging.getLogger("gismeteo")
class GismeteoApi(WeatherApi): class GismeteoApi(WeatherApi):
BASE_URL = "https://www.gismeteo.ru" SOURCE = ApiSource(
CACHE_TTL = 10 * 60 "https://www.gismeteo.ru",
cookies={
USER_AGENT = ( "cf_clearance": (
"Mozilla/5.0 (X11; Linux x86_64) " "zPj8qeaYZWp5BUZsWIRD7kd32s59IDWWaVvD7GGf6b4-1724254262-1.2.1.1-"
"AppleWebKit/537.36 (KHTML, like Gecko) " "R1PaHoqlm4OEgHfrOg6oAJmVmFJ7053JI_QDjIFlCAmbNY0oyw1J4QtgmEkAkTWF4C99X5hpXmZB2en."
"Chrome/126.0.0.0 Safari/537.36" "9Ey3NL0kzaE10UGBHPli5OLxHNKC3wQ34xmxTxg6GcKouXOPRgqo92lVRpQP7ghvDmvvT_"
"S6YXDbRonkamptWhZiAsIhsnIQg2Mt7Lk1fxSEVbaey_RXVQBvaR2ofiFgIavcbQPRFSvJ."
"Ct_FujmymTAZWh1XHTptK32kur81NXyPuARThetOKQm8AklaMa855Oom6Bms1a4F9b0yEHSd2inA4j3FR7uauu8hhwO0Z2goa3."
"ktpXXAQLz6dm.fBEWIHD7wooda15X57tCcDOely4hxhO4LK2lIH6TbOr."
"rZQAiRRhltHiCizP1Ou2SiF_81lb1umoDh739tQD1cnw_USnL."
"JwTHvkB00ZnaHRMi4FCBrsKIE0NxJO6kiv1QANqumzf5.8_pSIGRo2cKeO8xCydduDNFbStdOmLR6FU7ZKqVu"
) )
COOKIE = (
"cf_clearance=U28mYVC0ENu88vorlL_CWmWOoevvXp0vb4xCqfqYC9s-"
"1722273367-1.0.1.1-"
"IDV73azTHY0V.NAnmEvok3zf5HHEkvF098pmya7IiqRRB5nk3FhbLCb0AeWm_kpTFqi1niFk2mYN_ramGTSl0A"
)
async def _request(self, endpoint: str) -> str:
url = f"{self.BASE_URL}/{endpoint}"
logger.info(url)
async with aiohttp.ClientSession(
headers={
"User-Agent": self.USER_AGENT,
"Cookie": self.COOKIE,
}, },
raise_for_status=True, )
) as session: CACHE_TTL = 10 * 60
async with session.request("GET", url) as response:
return await response.text()
def _parse_oneday(self, date: datetime.date, data: str) -> WeatherResponse: def _parse_oneday(self, date: datetime.date, data: str) -> WeatherResponse:
result: List[Dict[str, Any]] = [] result: List[Dict[str, Any]] = []
@@ -88,10 +78,10 @@ class GismeteoApi(WeatherApi):
@cached(ttl=CACHE_TTL) @cached(ttl=CACHE_TTL)
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse: async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
data = await self._request(f"weather-{location_id}/{datehelp.dump(date)}") data = await self.SOURCE.request(f"weather-{location_id}/{datehelp.dump(date)}")
return self._parse_oneday(date, data) return self._parse_oneday(date, data)
@cached(ttl=CACHE_TTL) @cached(ttl=CACHE_TTL)
async def get_days(self, location_id: str, days: int) -> WeatherResponse: async def get_days(self, location_id: str, days: int) -> WeatherResponse:
data = await self._request(f"weather-{location_id}/{days}-days") data = await self.SOURCE.request(f"weather-{location_id}/{days}-days")
return self._parse_manydays(data) return self._parse_manydays(data)

View File

@@ -1,39 +1,21 @@
import datetime import datetime
import logging import logging
import aiohttp
from aiocache import cached from aiocache import cached
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from gallery.sketch.schedule.api import ScheduleApi from gallery.sketch.schedule.api import ScheduleApi
from gallery.sketch.schedule.catalog import ChannelId from gallery.sketch.schedule.catalog import ChannelId
from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue
from gallery.sketch.source import ApiSource
logger = logging.getLogger("matchtv") logger = logging.getLogger("matchtv")
class MatchTvApi(ScheduleApi): class MatchTvApi(ScheduleApi):
BASE_URL = "https://matchtv.ru" SOURCE = ApiSource("https://matchtv.ru")
CACHE_TTL = 30 * 60 CACHE_TTL = 30 * 60
USER_AGENT = (
"Mozilla/5.0 (X11; Linux x86_64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/126.0.0.0 Safari/537.36"
)
async def _request(self, endpoint: str) -> str:
url = f"{self.BASE_URL}/{endpoint}"
logger.info(url)
async with aiohttp.ClientSession(
headers={
"User-Agent": self.USER_AGENT,
},
raise_for_status=True,
) as session:
async with session.request("GET", url) as response:
return await response.text()
async def get_channels(self) -> list[str]: async def get_channels(self) -> list[str]:
return [ return [
ChannelId.MATCH_TV, ChannelId.MATCH_TV,
@@ -50,7 +32,7 @@ class MatchTvApi(ScheduleApi):
self, channel_id: str, date: datetime.date self, channel_id: str, date: datetime.date
) -> Schedule: ) -> Schedule:
endpoint = f"channel/{channel_id}/tvguide?date={date:%d-%m-%Y}" endpoint = f"channel/{channel_id}/tvguide?date={date:%d-%m-%Y}"
data = await self._request(endpoint) data = await self.SOURCE.request(endpoint)
soup = BeautifulSoup(data, features="html.parser") soup = BeautifulSoup(data, features="html.parser")
values = [] values = []
channel_name = soup.select_one(".caption__heading").text.split("|")[0].strip() channel_name = soup.select_one(".caption__heading").text.split("|")[0].strip()

40
gallery/sketch/source.py Normal file
View File

@@ -0,0 +1,40 @@
import logging
import aiohttp
logger = logging.getLogger("source")
class ApiSource:
DEFAULT_USER_AGENT = (
"Mozilla/5.0 (X11; Linux x86_64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/126.0.0.0 Safari/537.36"
)
DEFAULT_TIMEOUT = 30.0
def __init__(
self,
base_url,
user_agent: str = DEFAULT_USER_AGENT,
timeout: float = DEFAULT_TIMEOUT,
cookies: dict[str, str] | None = None,
):
self._base_url = base_url
self._user_agent = user_agent
self._timeout = timeout
self._cookies = cookies
async def request(self, endpoint: str) -> str:
url = f"{self._base_url}/{endpoint}"
logger.info(url)
headers = {
"User-Agent": self._user_agent,
}
async with aiohttp.ClientSession(
headers=headers,
cookies=self._cookies,
raise_for_status=True,
) as session:
async with session.request("GET", url, timeout=self._timeout) as response:
return await response.text()