2025-01-20 12:04:20 +09:00

113 lines
4.1 KiB
Python

import logging
from datetime import date, datetime, timedelta
from typing import List
from xml.sax.saxutils import unescape
from epg2xml.providers import EPGProgram, EPGProvider
log = logging.getLogger(__name__.rsplit(".", maxsplit=1)[-1].upper())
GENRE_CODE = {
"1": "드라마",
"2": "영화",
"4": "만화",
"8": "스포츠",
"9": "교육",
"11": "홈쇼핑",
"13": "예능",
"14": "시사/다큐",
"15": "음악",
"16": "라이프",
"17": "교양",
"18": "뉴스",
}
class SK(EPGProvider):
"""EPGProvider for SK
데이터: jsonapi
요청수: #channels
특이사항:
- 최대 3일치를 한 번에
"""
referer = "https://www.bworld.co.kr/"
title_regex = r"^(.*?)(\(([\d,]+)회\))?(<(.*)>)?(\((재)\))?$"
def get_svc_channels(self) -> List[dict]:
svc_channels = []
url = "https://www.bworld.co.kr/content/realtime/realtime_list.ajax"
params = {"pack": "PM50305785"}
c_name = ""
for x in self.request(url, params=params):
if x["depth"] == "1":
c_name = x["m_name"]
elif x["depth"] == "2" and c_name and c_name not in ["프로모션"]:
svc_channels.append(
{
"Name": unescape(x["m_name"]),
"No": str(x["ch_no"]),
"ServiceId": x["id_svc"],
"Category": c_name,
}
)
return svc_channels
def get_programs(self) -> None:
max_ndays = 3
if int(self.cfg["FETCH_LIMIT"]) > max_ndays:
log.warning(
"""
***********************************************************************
%s는 당일포함 %d일치만 EPG를 제공하고 있습니다.
***********************************************************************
""",
self.provider_name,
max_ndays,
)
url = "https://www.bworld.co.kr/myb/core-prod/product/btv-channel/week-frmt-list"
params = {"idSvc": "SVCID", "stdDt": "EPGDATE", "gubun": "week"}
for idx, _ch in enumerate(self.req_channels):
log.info("%03d/%03d %s", idx + 1, len(self.req_channels), _ch)
params.update({"idSvc": _ch.svcid, "stdDt": date.today().strftime("%Y%m%d")})
try:
infolist = self.request(url, params=params)["result"]["chnlFrmtInfoList"]
assert isinstance(infolist, list)
except Exception:
log.exception("예상치 못한 응답: %s", params)
continue
for nd in range(min(int(self.cfg["FETCH_LIMIT"]), max_ndays)):
day = date.today() + timedelta(days=nd)
try:
_epgs = self.__epgs_of_day(_ch.id, infolist, day)
except Exception:
log.exception("프로그램 파싱 중 예외: %s, %s", _ch, day)
else:
_ch.programs.extend(_epgs)
def __epgs_of_day(self, channelid: str, data: list, day: datetime) -> List[EPGProgram]:
_epgs = []
for info in data:
if info["eventDt"] != day.strftime("%Y%m%d"):
continue
_epg = EPGProgram(channelid)
_epg.title = info["nmTitle"]
if m := self.title_regex.match(_epg.title):
_epg.title = m.group(1)
_epg.title_sub = m.group(5)
_epg.rebroadcast = bool(m.group(7))
_epg.ep_num = m.group(3)
_epg.rating = int(info.get("cdRating") or "0")
_epg.stime = datetime.strptime(info["dtEventStart"], "%Y%m%d%H%M%S")
_epg.etime = datetime.strptime(info["dtEventEnd"], "%Y%m%d%H%M%S")
if info["cdGenre"] and (info["cdGenre"] in GENRE_CODE):
_epg.categories = [GENRE_CODE[info["cdGenre"]]]
_epg.desc = info["nmSynop"] or None # 값이 없음
_epgs.append(_epg)
return _epgs