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