feat(api): add ApiSource
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
40
gallery/sketch/source.py
Normal 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()
|
||||||
Reference in New Issue
Block a user