113 lines
4.1 KiB
Python
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
|