Compare commits

...

6 Commits

Author SHA1 Message Date
wonipapa
25e01d13b0
Update README.md 2018-04-01 14:44:29 +09:00
wonipapa
ea63642b05
Delete LICENSE 2018-04-01 14:41:19 +09:00
wonipapa
0827e17940
Delete epg2xml-web.php 2018-04-01 14:41:06 +09:00
wonipapa
b871dbf76a
Delete epg2xml.php 2018-04-01 14:40:52 +09:00
wonipapa
1dd5de61e1
Delete epg2xml.py 2018-04-01 14:40:43 +09:00
wonipapa
bc002b4d14
Delete epg2xml.json 2018-04-01 14:40:27 +09:00
6 changed files with 1 additions and 1965 deletions

29
LICENSE
View File

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2017, wonipapa
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

253
README.md
View File

@ -1,252 +1 @@
# 공지
리포지터리 삭제되었습니다
# EPG2XML
이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2.7 및 php5.4.45 이상에서 사용 가능하도록 제작되었다.
python3과 php 5.4.45 이하에서는 정상적인 작동을 보장하지 못한다. 또한 외부의 소스를 분석하여 EPG 정보를 가공하여 보여주는 것이므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
## 개발자 후원하기
https://www.facebook.com/chericface
페이스북을 사용하신다면 개발자 후원하는 방법이라고 생각해주시고 위의 링크 들어가서 좋아요 눌러주시면 감사하겠습니다.
제가 관련된 곳에서 운영하는 페이스북인데 아직 초기라서 사람이 많이 없습니다. 화학공학 및 소재 관련 사이트입니다.
감사합니다.
## 필요 모듈
### epg2xml.py
BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.
설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.
pip install beautifulsoup4, pip install lxml, pip install requests 로 추가할 수 있다.
* easy_install로 설치시 모듈이 인식되지 않는 경우가 있으므로 pip로 설치하기를 권한다.
### epg2xml.php
json, dom, mbstring, openssl, curl 모듈이 필요하다. 일반적으로 PHP가 설치되어 있다면 대부분 설치되어 있는 모듈이나 설치되어 있지 않을 경우 추가로 설치해야 한다.
### epg2xml-web.php
epg2xml.php와 동일하다.
## 설정방법
### epg2xml.json
epg2xml.json 안의 항목이 설정 가능한 항목이다.
<pre>
MyISP : 사용하는 ISP를 넣는다 .(ALL, KT, LG, SK가 사용가능하다)
MyChannels : EPG 정보를 가져오고자 하는 채널 ID를 넣는다. ("1, 2, 3, 4" 또는 "1,2,3,4")
output : EPG 정보 출력방향 (d: 화면 출력, o: 파일 출력, s:소켓출력)
default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
default_rebroadcast : 제목에 재방송 정보 출력
default_episode : 제목에 회차정보 출력
default_verbose : EPG 정보 상세 출력
default_xmltvns : 에피소드 정보 표시 방법
default_fetch_limit : EPG 데이터 가져오는 기간.
default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.
default_xml_socket : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
</pre>
### Channel.json
Channel.json 파일의 최신버전은 https://github.com/wonipapa/Channel.json 에서 다운받을 수 있다.
Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다.
## 옵션 소개
### epg2xml.py, epg2xml.php 옵션
실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다.
epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
<pre>
-h --help : 도움말 출력
--version : 버전을 보여준다.
-i : IPTV 선택 (ALL, KT, SK, LG 선택가능) ex) -i KT
-d --display : EPG 정보를 화면으로 보여준다.
-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
-s --socket : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
--icon : 채널 icon 위치 URL ex) --icon http://www.example.com
--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
--episode : 제목에 회차정보 표기 ex) --episode y
--verbose : EPG 정보 상세하게 표기 ex) --verbose y
</pre>
### epg2xml-web.php 옵션
실행시 사용가능한 인수는 epg2xml.php?help 명령어로 확인이 가능하다.
epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
ex : http://domain/epg2xml.php?i=ALL&l=2
## 사용방법
### tv_grab_file 사용시 (https://github.com/nurtext/tv_grab_file_synology)
tv_grab_file 안의 cat xmltv.xml 또는 wget 이 있는 부분을 아래와 같이 변경해준다.
python 경로와 php의 경로는 /usr/bin에 있고, epg2xml 파일은 /home/hts에 있는 것으로 가정했다.
이 경우 epg2xml.json의 output을 d로 해야 한다.
#### PYTHON의 경우
<pre>
/usr/bin/python /home/hts/epg2xml.py 또는
/home/hts/epg2xml.py
</pre>
#### PHP CLI의 경우
<pre>
/usr/bin/php /home/hts/epg2xml.php 또는
/home/hts/epg2xml.php
</pre>
#### PHP WEB의 경우
<pre>
wget -O - http://www.examle.com/epg2xml-web.php 또는
wget -O - http://www.example.com/epg2xml-web.php?i=ALL&l=2
</pre>
### XMLTV SOCKET 사용시
**xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다**
#### PYTHON의 경우
<pre>
/usr/bin/python /home/hts/epg2xml.py 또는
/home/hts/epg2xml.py
</pre>
#### PHP CLI의 경우
<pre>
/usr/bin/php /home/hts/epg2xml.php 또는
/home/hts/epg2xml.php
</pre>
#### PHP WEB의 경우
php web 버전은 xmltv.sock을 지원하지 않는다.
## 라이센스
BSD 3-clause "New" or "Revised" License
## WIKI
https://github.com/wonipapa/epg2xml/wiki
## FAQ
https://github.com/wonipapa/epg2xml/wiki/FAQ
## 변경사항
### Version 1.2.6
- SKB 함수 버그 수정
- KT, LG, SK, SKB, NAVER 이외의 함수 삭제
### Version 1.2.5
- SKB 함수 수정
- SKB 함수 수정(p1)
- SKY 함수 수정(p2)
- HCN 함수 삭제(p3)
### Version 1.2.4
- ISCS 함수 수정
- SKB 함수 수정(p1)
### Version 1.2.3
- PHP 버전통합
- PYTHON 버전 html Parser 변수 추가(libxml지원안하는 기기 편의 지원)
- everyontv 함수 추가
- Channel.json Enabled 항목 제거
- 에피소드 넘버 xmltv_ns 옵션 항목 추가 (epg2xml.json)
- 가져오는 날짜 최대 7일로 변경
- KT 함수 수정
- PHP 버전 socket 사용시 화면에 출력되는 문제 해결(p1)
- PHP 버전 한글 깨지는 문제 수정(p2)
- SK 함수 수정(p3)
- 이터레이션 수정(p4)
- oksusu함수 추가(p4)
- PHP 버전 Pooq함수 복구(p5)
### Version 1.2.2
- My Channel 추가
- 소스 추가
- 에피소드 넘버 xmltv_ns 추가
- PHP 공용함수 분리
- POOQ 함수 기간에 관계없이 하루만 가져오는 것 수정
- ISCS 함수 수정
 - HCN 함수 수정
### Version 1.2.1
- SKB 함수 추가
- 가져오는 날짜 최대 2일로 변경
- 타이틀이 1부, 2부 등 을 포함할 때 1부, 2부를 서브타이틀로 이동
- Channel.json release date 삭제
- Channel.json 채널 기본 설정 Enalble 0으로 변경
- Channel 소스 변경
- GCN 채널 삭제
- readme.txt Readme.md로 통합
### Version 1.2.0
- 커넥션 관련 에러 예외 처리 추가
- 채널 소스 변경
- Channel.json release date 추가
### Version 1.1.9
- 언어 버전 사항 체크
- 필요 모듈 사항 체크
- 버그 수정
- php 버전 웹 버전 추가
- php 버전 file_get_contents를 curl 사용으로 수정
### Version 1.1.8
- KBS 함수 추가
- 채널 변경 사항 반영
- 스카이라이프 url 변경
- EPG 누락 데이터 수정
### Version 1.1.7
- PHP 7.0 지원
- 채널 변경 사항 반영
- 라디오 채널 추가
### Version 1.1.6
- iptv 선택 항목에 ALL 추가
- 에피소드 넘버 출력 수정
- 시작 시간 에러 출력 수정
- 타이틀 출력 수정
- 서브타이틀 추출 수정
- 데이터 중복 출력 문제 수정
- php 버전이 5.6.3 이전일 때 DOM access 관련 에러 수정
### Version 1.1.5
- inline 변수 재추가
### Version 1.1.4
- epg2xml.json 파일 도입
- inline 변수 삭제
- PHP 버전 추가
- 버그 수정
### Version 1.1.3
- 제목에 회차정보, 재방송 정보 추가시 오류 수정
### Version 1.1.2
- 재방송정보, 회차정보 옵션 추가
### Version 1.1.1
- sk 카테고리 오류 수정
### Version 1.1.0
- 채널 아이콘 추가
- 오류 메시지 통합
### Version 1.0.9
- 소켓파일이 없을 때 오류 추가
- 채널 변경 사항 반영
### Version 1.0.8
- 정지 시간 추가
- 오류 출력 구문 디버그시만 출력으로 변경
- 채널 소스 변경
### Version 1.0.7
- urllib2를 requests로 변경
- User Agent 변경
- 오류 처리 추가
- 채널 변경 사항 반영
- 채널 소스 변경
- 지역 지상파 채널 추가
### Version 1.0.6
- urllib를 urllib2로 변경
- User Agent 추가
- 채널 변경 사항 반영
### Version 1.0.5
- epg.co.kr의 epg 정보 못가져오는 것 수정
### Version 1.0.4
- KODI에서 사용가능하도록 수정
- 제목에서 서브타이틀 및 회차 분리
- 서브타이틀 추가
- 출연, 제작진 개인별로 분리
### Version 1.0.3
- Channel.json 파일 오류 수정
- LG를 소스로 하는 EPG 정보 기간 오류 수정
### Version 1.0.2
- ISP별 분리된 채널통합
- 개별 채널별 EPG 정보 수집가능하도록 Enabled 추가
- getMyChannel 함수 삭제
- 채널 변경 사항 반영
- KT TRU TV 채널 삭제
- ISP 선택 설정 추가
- EPG 정보 가져오는 기간 설정 추가
- 채널 아이콘 설정 URL 설정 추가
- tvheadend 전용 카테고리 추가
### Version 1.0.1
- EPG 소스 변경
- 등록된 채널 정보만 EPG 정보 가져오도록 설정
- IPTV별 개인화
### Version 1.0.0
- first release
Channel.json 파일및 Channel.json 리포지터리는 5월 1일부로 삭제하도록 하겠습니다.

View File

@ -1,997 +0,0 @@
<?php
@mb_internal_encoding("UTF-8");
@date_default_timezone_set('Asia/Seoul');
error_reporting(E_ALL ^ E_NOTICE);
@set_time_limit(0);
define("VERSION", "1.2.6");
$debug = False;
$ua = "'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116'";
$timeout = 5;
define("CHANNEL_ERROR", " 존재하지 않는 채널입니다.");
define("CONTENT_ERROR ", " EPG 정보가 없습니다.");
define("HTTP_ERROR", " EPG 정보를 가져오는데 문제가 있습니다.");
define("DISPLAY_ERROR", "EPG를 출력할 수 없습니다.");
define("FILE_ERROR", "XML 파일을 만들수 없습니다.");
define("SOCKET_ERROR", "소켓 파일을 찾을 수 없습니다.");
define("JSON_FILE_ERROR", "json 파일이 없습니다.");
define("JSON_SYNTAX_ERROR", "json 파일 형식이 잘못되었습니다.");
if(version_compare(PHP_VERSION, '5.4.45','<')) :
printError("PHP 버전은 5.4.45 이상이어야 합니다.");
printError("현재 PHP 버전은 ".PHP_VERSION." 입니다.");
exit;
endif;
if (!extension_loaded('json')) :
printError("json 모듈이 설치되지 않았습니다.");
exit;
endif;
if (!extension_loaded('dom')) :
printError("dom 모듈이 설치되지 않았습니다.");
exit;
endif;
if (!extension_loaded('mbstring')) :
printError("mbstring 모듈이 설치되지 않았습니다.");
exit;
endif;
if (!extension_loaded('openssl')) :
printError("openssl 모듈이 설치되지 않았습니다.");
exit;
endif;
if (!extension_loaded('curl')) :
printError("curl 모듈이 설치되지 않았습니다.");
exit;
endif;
//옵션 처리
$shortargs = "";
$shortargs .= "i:";
$shortargs .= "v";
$shortargs .= "d";
$shortargs .= "o:s:";
$shortargs .= "l:";
$shortargs .= "h";
$longargs = array(
"version",
"display",
"outfile:",
"socket:",
"limit::",
"icon:",
"episode:",
"rebroadcast:",
"verbose:",
"help"
);
$args = getopt($shortargs, $longargs);
$Settingfile = __DIR__."/epg2xml.json";
try {
$f = @file_get_contents($Settingfile);
if($f === False) :
printError("epg2xml.".JSON_FILE_ERROR);
exit;
else :
try {
$Settings = json_decode($f, TRUE);
if(json_last_error() != JSON_ERROR_NONE) throw new Exception("epg2xml.".JSON_SYNTAX_ERROR);
$MyISP = $Settings['MyISP'] ?: "ALL";
$MyChannels = isset($Settings['MyChannels']) ? $Settings['MyChannels'] : "";
$default_output = $Settings['output'] ?: "d";
$default_xml_file = $Settings['default_xml_file'] ?: "xmltv.xml";
$default_xml_socket = $Settings['default_xml_socket'] ?: "xmltv.sock";
$default_icon_url = $Settings['default_icon_url'] ?: "";
$default_fetch_limit = $Settings['default_fetch_limit'] ?: "2";
$default_rebroadcast = $Settings['default_rebroadcast'] ?: "y";
$default_episode = $Settings['default_episode'] ?: "y";
$default_verbose = $Settings['default_verbose'] ?: "n";
$default_xmltvns = $Settings['default_xmltvns'] ?: "n";
$userISP = !empty($_GET['i']) ? $_GET['i'] : (!empty($args['i']) ? $args['i'] : "");
$user_output = "";
$user_xml_file = "";
$user_xml_socket = "";
if(isset($_GET['d']) || isset($_GET['display']) || (isset($args['d']) && $args['d'] === False) || (isset($args['display']) && $args['display'] === False)):
if(isset($_GET['o']) || isset($_GET['outfile']) || isset($_GET['s']) || isset($_GET['socket']) || isset($args['o']) || isset($args['outfile']) || isset($args['s']) || isset($args['socket'])) :
printf($usage);
printf("epg2xml.php: error: argument -o/--outfile, -s/--socket: not allowed with argument -d/--display\n");
exit;
endif;
$user_output = "d";
elseif(isset($_GET['o']) || isset($_GET['outfile']) || isset($args['o']) || isset($args['outfile'])):
if(isset($_GET['d']) || isset($_GET['display']) || isset($_GET['s']) || isset($_GET['socket']) || isset($args['d']) || isset($args['display']) || isset($args['s']) || isset($args['socket'])) :
printf($usage);
printf("epg2xml.php: error: argument -d/--display, -s/--socket: not allowed with argument -o/--outfile\n");
exit;
endif;
$user_output = "o";
if(isset($_GET['o']) || isset($_GET['outfile'])) :
$user_xml_file = $_GET['o'] ?: $_GET['outfile'];
elseif(isset($args['o']) || isset($args['outfile'])) :
$user_xml_file = $args['o'] ?: $args['outfile'];
endif;
elseif(isset($_GET['s']) || isset($_GET['socket']) || isset($args['s']) || isset($args['socket'])):
if(isset($_GET['d']) || isset($_GET['display']) || isset($_GET['o']) || isset($_GET['outfile']) || isset($args['d']) || isset($args['display']) || isset($args['o']) || isset($args['outfile'])) :
printf($usage);
printf("epg2xml.php: error: argument -d/--display, -o/--outfile: not allowed with argument -s/--socket\n");
exit;
endif;
$user_output = "s";
if(isset($_GET['s']) || isset($_GET['socket'])) :
$user_xml_socket = $_GET['s'] ?: $_GET['socket'];
elseif(isset($args['s']) || isset($args['socket'])) :
$user_xml_socket = $args['s'] ?: $args['socket'];
endif;
endif;
$user_fetch_limit = "";
$user_icon_url = empty($_GET['icon']) === False ? $_GET['icon'] : (empty($args['icon']) === False ? $args['icon'] : "");
if(isset($_GET['l']) || isset($_GET['limit']) || isset($args['l']) || isset($args['limit'])):
if(isset($_GET['l']) || isset($_GET['limit'])) :
$user_fetch_limit = $_GET['l'] ?: $_GET['limit'];
elseif(isset($args['l']) || isset($args['limit'])) :
$user_fetch_limit = $args['l'] ?: $args['limit'];
endif;
endif;
$user_rebroadcast = empty($_GET['rebroadcast']) === False ? $_GET['rebroadcast'] : (empty($args['rebroadcast']) === False ? $args['rebroadcast'] : "");
$user_episode = empty($_GET['episode']) === False ? $_GET['episode'] : (empty($args['episode']) === False ? $args['episode'] : "");
$user_verbose = empty($_GET['verbose']) === False ? $_GET['verbose'] : (empty($args['verbose']) === False ? $args['verbose'] : "");
if(!empty($userISP)) $MyISP = $userISP;
if(!empty($user_output)) $default_output = $user_output;
if(!empty($user_xml_file)) $default_xml_file = $user_xml_file;
if(!empty($user_xml_socket)) $default_xml_socket = $user_xml_socket;
if(!empty($user_icon_url)) $default_icon_url = $user_icon_url;
if(!empty($user_fetch_limit)) $default_fetch_limit = $user_fetch_limit;
if(!empty($user_rebroadcast)) $default_rebroadcast = $user_rebroadcast;
if(!empty($user_episode)) $default_episode = $user_episode;
if(!empty($user_verbose)) $default_verbose = $user_verbose;
if(empty($MyISP)) : //ISP 선택없을 시 사용법 출력
printError("epg2xml.json 파일의 MyISP항목이 없습니다.");
exit;
else :
if(!in_array($MyISP, array("ALL", "KT", "LG", "SK"))) : //ISP 선택
printError("MyISP는 ALL, KT, LG, SK만 가능합니다.");
exit;
endif;
endif;
if(empty($default_output)) :
printError("epg2xml.json 파일의 output항목이 없습니다.");
exit;
else :
if(in_array($default_output, array("d", "o", "s"))) :
switch ($default_output) :
case "d" :
$output = "display";
break;
case "o" :
$output = "file";
break;
case "s" :
$output = "socket";
break;
endswitch;
else :
printError("output는 d, o, s만 가능합니다.");
exit;
endif;
endif;
if(empty($default_fetch_limit)) :
printError("epg2xml.json 파일의 default_fetch_limit항목이 없습니다.");
exit;
else :
if(in_array($default_fetch_limit, array(1, 2, 3, 4, 5, 6, 7))) :
$period = $default_fetch_limit;
else :
printError("default_fetch_limit는 1, 2, 3, 4, 5, 6, 7만 가능합니다.");
exit;
endif;
endif;
if(is_null($default_icon_url) == True) :
printError("epg2xml.json 파일의 default_icon_url항목이 없습니다.");
exit;
else :
$IconUrl = $default_icon_url;
endif;
if(empty($default_rebroadcast)) :
printError("epg2xml.json 파일의 default_rebroadcast항목이 없습니다.");
exit;
else :
if(in_array($default_rebroadcast, array("y", "n"))) :
$addrebroadcast = $default_rebroadcast;
else :
printError("default_rebroadcast는 y, n만 가능합니다.");
exit;
endif;
endif;
if(empty($default_episode)) :
printError("epg2xml.json 파일의 default_episode항목이 없습니다.");
exit;
else :
if(in_array($default_episode, array("y", "n"))) :
$addepisode = $default_episode;
else :
printError("default_episode는 y, n만 가능합니다.");
exit;
endif;
endif;
if(empty($default_verbose)) :
printError("epg2xml.json 파일의 default_verbose항목이 없습니다.");
exit;
else :
if(in_array($default_verbose, array("y", "n"))) :
$addverbose = $default_verbose;
else :
printError("default_verbose는 y, n만 가능합니다.");
exit;
endif;
endif;
if(empty($default_xmltvns)) :
printError("epg2xml.json 파일의 default_xmltvns항목이 없습니다.");
exit;
else :
if(in_array($default_xmltvns, array("y", "n"))) :
$addxmltvns = $default_xmltvns;
else :
printError("default_xmltvns는 y, n만 가능합니다.");
exit;
endif;
endif;
}
catch(Exception $e) {
printError($e->getMessage());
exit;
}
endif;
}
catch(Exception $e) {
printError($e->getMessage());
exit;
}
if(php_sapi_name() != "cli"):
if(isset($_GET['h']) || isset($_GET['help']))://도움말 출력
header("Content-Type: text/plain; charset=utf-8");
print($help);
exit;
elseif(isset($_GET['v'])|| isset($_GET['version']))://버전 정보 출력
header("Content-Type: text/plain; charset=utf-8");
printf("epg2xml.php version : %s\n", VERSION);
exit;
endif;
else :
if((isset($args['h']) && $args['h'] === False) || (isset($args['help']) && $args['help'] === False))://도움말 출력
printf($help);
exit;
elseif((isset($args['v']) && $args['v'] === False) || (isset($args['version']) && $args['version'] === False))://버전 정보 출력
printf("epg2xml.php version : %s\n", VERSION);
exit;
endif;
endif;
if($output == "display") :
$fp = fopen('php://output', 'w+');
if ($fp === False) :
printError(DISPLAY_ERROR);
exit;
else :
try {
getEpg();
fclose($fp);
} catch(Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endif;
elseif($output == "file") :
if($default_xml_file) :
$fp = fopen($default_xml_file, 'w+');
if ($fp === False) :
printError(FIEL_ERROR);
exit;
else :
try {
getEpg();
fclose($fp);
} catch(Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endif;
else :
printError("epg2xml.json 파일의 default_xml_file항목이 없습니다.");
exit;
endif;
elseif($output == "socket") :
if($default_xml_socket && php_sapi_name() == "cli") :
$default_xml_socket = "unix://".$default_xml_socket;
$fp = @fsockopen($default_xml_socket, -1, $errno, $errstr, 30);
if ($fp === False) :
printError(SOCKET_ERROR);
exit;
else :
try {
getEpg();
fclose($fp);
} catch(Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endif;
else :
printError("epg2xml.json 파일의 default_xml_socket항목이 없습니다.");
exit;
endif;
endif;
function getEPG() {
$fp = $GLOBALS['fp'];
$MyISP = $GLOBALS['MyISP'];
$MyChannels = $GLOBALS['MyChannels'];
$Channelfile = __DIR__."/Channel.json";
$IconUrl = "";
$ChannelInfos = array();
try {
$f = @file_get_contents($Channelfile);
if($f === False) :
printError("Channel.json.".JSON_FILE_ERROR);
exit;
else :
try {
$Channeldatajson = json_decode($f, TRUE);
if(json_last_error() != JSON_ERROR_NONE) throw new Exception("Channel.".JSON_SYNTAX_ERROR);
}
catch(Exception $e) {
printError($e->getMessage());
exit;
}
endif;
}
catch(Exception $e) {
printError($e->getMessage());
exit;
}
//My Channel 정의
$MyChannelInfo = array();
if($MyChannels) :
$MyChannelInfo = array_map('trim',explode(',', $MyChannels));
endif;
if(php_sapi_name() != "cli" && $GLOBALS['default_output'] == "d") header("Content-Type: application/xml; charset=utf-8");
fprintf($fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fprintf($fp, "<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n");
fprintf($fp, "<tv generator-info-name=\"epg2xml %s\">\n", VERSION);
foreach ($Channeldatajson as $Channeldata) : //Get Channel & Print Channel info
if(in_array($Channeldata['Id'], $MyChannelInfo)) :
$ChannelId = $Channeldata['Id'];
$ChannelName = htmlspecialchars($Channeldata['Name'], ENT_XML1);
$ChannelSource = $Channeldata['Source'];
$ChannelServiceId = $Channeldata['ServiceId'];
$ChannelIconUrl = htmlspecialchars($Channeldata['Icon_url'], ENT_XML1);
if($MyISP != "ALL" && $Channeldata[$MyISP.'Ch'] != Null):
$ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId);
$Channelnumber = $Channeldata[$MyISP.'Ch'];
$ChannelISPName = htmlspecialchars($Channeldata[$MyISP." Name"], ENT_XML1);
fprintf($fp, " <channel id=\"%s\">\n", $ChannelId);
fprintf($fp, " <display-name>%s</display-name>\n", $ChannelName);
fprintf($fp, " <display-name>%s</display-name>\n", $ChannelISPName);
fprintf($fp, " <display-name>%s</display-name>\n", $Channelnumber);
fprintf($fp, " <display-name>%s</display-name>\n", $Channelnumber." ".$ChannelISPName);
if($IconUrl) :
fprintf($fp, " <icon src=\"%s/%s.png\" />\n", $IconUrl, $ChannelId);
else :
fprintf($fp, " <icon src=\"%s\" />\n", $ChannelIconUrl);
endif;
fprintf($fp, " </channel>\n");
elseif($MyISP == "ALL"):
$ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId);
fprintf($fp, " <channel id=\"%s\">\n", $ChannelId);
fprintf($fp, " <display-name>%s</display-name>\n", $ChannelName);
if($IconUrl) :
fprintf($fp, " <icon src=\"%s/%s.png\" />\n", $IconUrl, $ChannelId);
else :
fprintf($fp, " <icon src=\"%s\" />\n", $ChannelIconUrl);
endif;
fprintf($fp, " </channel>\n");
endif;
endif;
endforeach;
// Print Program Information
foreach ($ChannelInfos as $ChannelInfo) :
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ChannelSource = $ChannelInfo[2];
$ChannelServiceId = $ChannelInfo[3];
if($GLOBALS['debug']) printLog($ChannelName.' 채널 EPG 데이터를 가져오고 있습니다');
if($ChannelSource == 'KT') :
GetEPGFromKT($ChannelInfo);
elseif($ChannelSource == 'LG') :
GetEPGFromLG($ChannelInfo);
elseif($ChannelSource == 'SK') :
GetEPGFromSK($ChannelInfo);
elseif($ChannelSource == 'SKB') :
GetEPGFromSKB($ChannelInfo);
elseif($ChannelSource == 'NAVER') :
GetEPGFromNaver($ChannelInfo);
endif;
endforeach;
fprintf($fp, "</tv>\n");
}
// Get EPG data from KT
function GetEPGFromKT($ChannelInfo) {
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ServiceId = $ChannelInfo[3];
$epginfo = array();
foreach(range(1, $GLOBALS['period']) as $k) :
$url = "http://tv.kt.com/tv/channel/pSchedule.asp";
$day = date("Ymd", strtotime("+".($k - 1)." days"));
$params = array(
'ch_type' => '1',
'view_type' => '1',
'service_ch_no' => $ServiceId,
'seldate' => $day
);
$params = http_build_query($params);
$method = "POST";
try {
$response = getWeb($url, $params, $method);
if ($response === False && $GLOBALS['debug']) :
printError($ChannelName.HTTP_ERROR);
else :
$response = mb_convert_encoding($response, "HTML-ENTITIES", "EUC-KR");
$dom = new DomDocument;
libxml_use_internal_errors(True);
if($dom->loadHTML('<?xml encoding="utf-8" ?>'.$response)):
$xpath = new DomXPath($dom);
$query = "//tbody/tr";
$rows = $xpath->query($query);
foreach($rows as $row) :
$startTime = $endTime = $programName = $subprogramName = $desc = $actors = $producers = $category = $episode = "";
$rebroadcast = False;
$rating = 0;
$cells = $row->getElementsByTagName('td');
$programs = array_map(null, iterator_to_array($xpath->query('p', $cells->item(1))), iterator_to_array($xpath->query('p', $cells->item(2))), iterator_to_array($xpath->query('p', $cells->item(3))));
foreach($programs as $program):
$hour = trim($cells->item(0)->nodeValue);
$minute = trim($program[0]->nodeValue);
$startTime = date("YmdHis", strtotime($day.$hour.$minute."00"));
$programName = trim($program[1]->nodeValue);
$images = $program[1]->getElementsByTagName('img')->item(0);
preg_match('/([\d,]+)/', $images->getAttribute('alt'), $grade);
if($grade != NULL):
$rating = $grade[1];
else:
$rating = 0;
endif;
$programName = str_replace("방송중 ", "", $programName);
$category = trim($program[2]->nodeValue);
//ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
$epginfo[] = array($ChannelId, $startTime, $programName, $subprogramName, $desc, $actors, $producers, $category, $episode, $rebroadcast, $rating);
usleep(1000);
endforeach;
endforeach;
else :
if($GLOBALS['debug']) printError($ChannelName.CONTENT_ERROR);
endif;
endif;
} catch (Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endforeach;
if($epginfo) epgzip($epginfo);
}
// Get EPG data from LG
function GetEPGFromLG($ChannelInfo) {
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ServiceId = $ChannelInfo[3];
$epginfo = array();
foreach(range(1, $GLOBALS['period']) as $k) :
$url = "http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi";
$day = date("Ymd", strtotime("+".($k - 1)." days"));
$params = array(
'chnlCd' => $ServiceId,
'evntCmpYmd' => $day
);
$params = http_build_query($params);
$method = "POST";
try {
$response = getWeb($url, $params, $method);
if ($response === False && $GLOBALS['debug']) :
printError($ChannelName.HTTP_ERROR);
else :
$response = mb_convert_encoding($response, "UTF-8", "EUC-KR");
$response = str_replace(array('<재>', ' [..', ' (..'), array('&lt;재&gt;', '', ''), $response);
$dom = new DomDocument;
libxml_use_internal_errors(True);
if($dom->loadHTML('<?xml encoding="utf-8" ?>'.$response)):
$xpath = new DomXPath($dom);
$query = "//div[@class='tblType list']/table/tbody/tr";
$rows = $xpath->query($query);
foreach($rows as $row) :
$startTime = $endTime = $programName = $subprogramName = $desc = $actors = $producers = $category = $episode = "";
$rebroadcast = False;
$rating = 0;
$cells = $row->getElementsByTagName('td');
$startTime = date("YmdHis", strtotime($day." ".trim($cells->item(0)->nodeValue)));
$programName = trim($cells->item(1)->childNodes->item(0)->nodeValue);
$pattern = '/(<재>)?\s?(?:\[.*?\])?(.*?)(?:\[(.*)\])?\s?(?:\(([\d,]+)회\))?$/';
preg_match($pattern, $programName, $matches);
if ($matches != NULL) :
if(isset($matches[2])) $programName = trim($matches[2]) ?: "";
if(isset($matches[3])) $subprogramName = trim($matches[3]) ?: "";
if(isset($matches[4])) $episode = trim($matches[4]) ?: "";
if(isset($matches[1])) $rebroadcast = trim($matches[1]) ? True: False;
endif;
$category = trim($cells->item(2)->nodeValue);
$spans = $cells->item(1)->getElementsByTagName('span');
$rating = trim($spans->item(1)->nodeValue)=="All" ? 0 : trim($spans->item(1)->nodeValue);
//ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
$epginfo[] = array($ChannelId, $startTime, $programName, $subprogramName, $desc, $actors, $producers, $category, $episode, $rebroadcast, $rating);
usleep(1000);
endforeach;
else :
if($GLOBALS['debug']) printError($ChannelName.CONTENT_ERROR);
endif;
endif;
} catch (Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endforeach;
if($epginfo) epgzip($epginfo);
}
// Get EPG data from SK
function GetEPGFromSK($ChannelInfo) {
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ServiceId = $ChannelInfo[3];
$today = date("Ymd");
$lastday = date("Ymd", strtotime("+".($GLOBALS['period'] - 1)." days"));
$url = "http://m.btvplus.co.kr/common/inc/IFGetData.do";
$params = array(
'variable' => 'IF_LIVECHART_DETAIL',
'pcode' => '|^|start_time='.$today.'00|^|end_time='.$lastday.'24|^|svc_id='.$ServiceId
);
$params = http_build_query($params);
$method = "POST";
try {
$response = getWeb($url, $params, $method);
if ($response === False && $GLOBALS['debug']) :
printError($ChannelName.HTTP_ERROR);
else :
try {
$data = json_decode($response, TRUE);
if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR);
if($data['channel'] == NULL) :
if($GLOBALS['debug']) :
printError($ChannelName.CHANNEL_ERROR);
endif;
else :
$programs = $data['channel']['programs'];
foreach ($programs as $program) :
$startTime = $endTime = $programName = $subprogramName = $desc = $actors = $producers = $category = $episode = "";
$rebroadcast = False;
$rating = 0;
$pattern = '/^(.*?)(?:\s*[\(<]([\d,회]+)[\)>])?(?:\s*<([^<]*?)>)?(\((재)\))?$/';
preg_match($pattern, str_replace('...', '>', $program['programName']), $matches);
if ($matches != NULL) :
if(isset($matches[1])) $programName = trim($matches[1]) ?: "";
if(isset($matches[3])) $subprogramName = trim($matches[3]) ?: "";
if(isset($matches[2])) $episode = str_replace("", "", $matches[2]) ?: "";
if(isset($matches[5])) $rebroadcast = $matches[5] ? True : False;
endif;
$startTime = date("YmdHis",$program['startTime']/1000);
$endTime = date("YmdHis",$program['endTime']/1000);
$desc = $program['synopsis'] ?: "";
$actors =trim(str_replace('...','',$program['actorName']), ', ') ?: "";
$producers = trim(str_replace('...','',$program['directorName']), ', ') ?: "";
if ($program['mainGenreName'] != NULL) :
$category = $program['mainGenreName'];
else:
$category = "";
endif;
$rating = $program['ratingCd'] ?: 0;
$programdata = array(
'channelId'=> $ChannelId,
'startTime' => $startTime,
'endTime' => $endTime,
'programName' => $programName,
'subprogramName'=> $subprogramName,
'desc' => $desc,
'actors' => $actors,
'producers' => $producers,
'category' => $category,
'episode' => $episode,
'rebroadcast' => $rebroadcast,
'rating' => $rating
);
writeProgram($programdata);
usleep(1000);
endforeach;
endif;
} catch(Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endif;
} catch (Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
}
// Get EPG data from SKB
function GetEPGFromSKB($ChannelInfo) {
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ServiceId = $ChannelInfo[3];
$epginfo = array();
foreach(range(1, $GLOBALS['period']) as $k) :
$url = "http://m.skbroadband.com/content/realtime/Channel_List.do";
$day = date("Ymd", strtotime("+".($k - 1)." days"));
$params = array(
'key_depth2' => $ServiceId,
'key_depth3' => $day
);
$params = http_build_query($params);
$method = "POST";
try {
$response = getWeb($url, $params, $method);
if ($response === False && $GLOBALS['debug']) :
printError($ChannelName.HTTP_ERROR);
else :
$response = str_replace('charset="EUC-KR"', 'charset="UTF-8"', $response);
$response = mb_convert_encoding($response, "UTF-8", "EUC-KR");
$response = preg_replace('/<!--(.*?)-->/is', '', $response);
$response = preg_replace('/<span class="round_flag flag02">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag03">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag04">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag09">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag10">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag11">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<span class="round_flag flag12">(.*?)<\/span>/', '', $response);
$response = preg_replace('/<strong class="hide">프로그램 안내<\/strong>/', '', $response);
$response = preg_replace_callback('/<p class="cont">(.*)/', 'converthtmlspecialchars', $response);
$response = preg_replace_callback('/<p class="tit">(.*)/', 'converthtmlspecialchars', $response);
$dom = new DomDocument;
libxml_use_internal_errors(True);
if($dom->loadHTML('<?xml encoding="utf-8" ?>'.$response)):
$xpath = new DomXPath($dom);
$query = "//span[@class='caption' or @class='explan' or @class='fullHD' or @class='UHD' or @class='nowon']";
$spans = $xpath->query($query);
foreach($spans as $span) :
$span->parentNode->removeChild( $span);
endforeach;
$query = "//div[@id='uiScheduleTabContent']/div/ol/li";
$rows = $xpath->query($query);
foreach($rows as $row) :
$startTime = $endTime = $programName = $subprogramName = $desc = $actors = $producers = $category = $episode = "";
$rebroadcast = False;
$rating = 0;
$cells = $row->getElementsByTagName('p');
$startTime = $cells->item(0)->nodeValue ?: "";
$startTime = date("YmdHis", strtotime($day." ".$startTime));
$programName = trim($cells->item(1)->childNodes->item(0)->nodeValue) ?: "";
$pattern = '/^(.*?)(\(([\d,]+)회\))?(<(.*)>)?(\((재)\))?$/';
preg_match($pattern, $programName, $matches);
if ($matches != NULL) :
if(isset($matches[1])) $programName = trim($matches[1]) ?: "";
if(isset($matches[5])) $subprogramName = trim($matches[5]) ?: "";
if(isset($matches[3])) $episode = $matches[3] ?: "";
if(isset($matches[7])) $rebroadcast = $matches[7] ? True : False;
endif;
if(trim($cells->item(1)->childNodes->item(1)->nodeValue)) $rating = str_replace('세 이상', '', trim($cells->item(1)->childNodes->item(1)->nodeValue)) ?: 0;
//ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
$epginfo[] = array($ChannelId, $startTime, $programName, $subprogramName, $desc, $actors, $producers, $category, $episode, $rebroadcast, $rating);
usleep(1000);
endforeach;
else :
if($GLOBALS['debug']) printError($ChannelName.CONTENT_ERROR);
endif;
endif;
} catch (Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endforeach;
if($epginfo) epgzip($epginfo);
}
// Get EPG data from Naver
function GetEPGFromNaver($ChannelInfo) {
$ChannelId = $ChannelInfo[0];
$ChannelName = $ChannelInfo[1];
$ServiceId = $ChannelInfo[3];
$epginfo = array();
$totaldate = array();
$url = "https://search.naver.com/p/csearch/content/batchrender_ssl.nhn";
foreach(range(1, $GLOBALS['period']) as $k) :
$day = date("Ymd", strtotime("+".($k - 1)." days"));
$totaldate[] = $day;
endforeach;
$params = array(
'_callback' => 'epg',
'fileKey' => 'single_schedule_channel_day',
'pkid' => '66',
'u1' => 'single_schedule_channel_day',
'u2' => join(",", $totaldate),
'u3' => $day,
'u4' => $GLOBALS['period'],
'u5' => $ServiceId,
'u6' => 1,
'u7' => $ChannelName."편성표",
'u8' => $ChannelName."편성표",
'where' => 'nexearch'
);
$params = http_build_query($params);
$method = "GET";
try {
$response = getWeb($url, $params, $method);
if ($response === False && $GLOBALS['debug']) :
printError($ChannelName.HTTP_ERROR);
else :
try {
$response = str_replace('epg( ', '', $response );
$response = substr($response, 0, strlen($response)-2);
$response = preg_replace("/\/\*.*?\*\//","",$response);
$data = json_decode($response, TRUE);
if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR);
if($data['displayDates'][0]['count'] == 0) :
if($GLOBALS['debug']) :
printError($ChannelName.CHANNEL_ERROR);
endif;
else :
for($i = 0; $i < count($data['displayDates']); $i++) :
for($j = 0; $j < 24; $j++) :
foreach($data['schedules'][$j][$i] as $program) :
$startTime = $endTime = $programName = $subprogramName = $desc = $actors = $producers = $category = $episode = "";
$rebroadcast = False;
$rating = 0;
$startTime = date("YmdHis", strtotime($data['displayDates'][$i]['date']." ".$program['startTime']));
$programName = htmlspecialchars_decode(trim($program['title']), ENT_XML1);
$episode = str_replace("","", $program['episode']);
$rebroadcast = $program['isRerun'] ? True : False;
$rating = $program['grade'];
//ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
$epginfo[] = array($ChannelId, $startTime, $programName, $subprogramName, $desc, $actors, $producers, $category, $episode, $rebroadcast, $rating);
usleep(1000);
endforeach;
endfor;
endfor;
endif;
} catch(Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
endif;
} catch (Exception $e) {
if($GLOBALS['debug']) printError($e->getMessage());
}
if($epginfo) epgzip($epginfo);
}
# Zip epginfo
function epgzip($epginfo) {
$epg1 = current($epginfo);
array_shift($epginfo);
foreach($epginfo as $epg2):
$ChannelId = $epg1[0] ?: "";
$startTime = $epg1[1] ?: "";
$endTime = $epg2[1] ?: "";
$programName = $epg1[2] ?: "";
$subprogramName = $epg1[3] ?: "";
$desc = $epg1[4] ?: "";
$actors = $epg1[5] ?: "";
$producers = $epg1[6] ?: "";
$category = $epg1[7] ?: "";
$episode = $epg1[8] ?: "";
$rebroadcast = $rebroadcast = $epg1[9] ? True: False;
$rating = $epg1[10] ?: 0;
$programdata = array(
'channelId'=> $ChannelId,
'startTime' => $startTime,
'endTime' => $endTime,
'programName' => $programName,
'subprogramName'=> $subprogramName,
'desc' => $desc,
'actors' => $actors,
'producers' => $producers,
'category' => $category,
'episode' => $episode,
'rebroadcast' => $rebroadcast,
'rating' => $rating
);
writeProgram($programdata);
$epg1 = $epg2;
endforeach;
}
function writeProgram($programdata) {
$fp = $GLOBALS['fp'];
$ChannelId = $programdata['channelId'];
$startTime = $programdata['startTime'];
$endTime = $programdata['endTime'];
$programName = trim(htmlspecialchars($programdata['programName'], ENT_XML1));
$subprogramName = trim(htmlspecialchars($programdata['subprogramName'], ENT_XML1));
preg_match('/(.*) \(?(\d+부)\)?/', $programName, $matches);
if ($matches != NULL) :
if(isset($matches[1])) $programName = trim($matches[1]) ?: "";
if(isset($matches[2])) $subprogramName = trim($matches[2]." ".$subprogramName) ?: "";
endif;//
if($programName == NULL):
$programName = $subprogramName;
endif;
$actors = htmlspecialchars($programdata['actors'], ENT_XML1);
$producers = htmlspecialchars($programdata['producers'], ENT_XML1);
$category = htmlspecialchars($programdata['category'], ENT_XML1);
$episode = $programdata['episode'];
if($episode) :
$episode_ns = (int)$episode - 1;
$episode_ns = '0' . '.' . $episode_ns . '.' . '0' . '/' . '0';
$episode_on = $episode;
endif;
$rebroadcast = $programdata['rebroadcast'];
if($episode && $GLOBALS['addepisode'] == 'y') $programName = $programName." (".$episode."회)";
if($rebroadcast == True && $GLOBALS['addrebroadcast'] == 'y') $programName = $programName." (재)";
if($programdata['rating'] == 0) :
$rating = "전체 관람가";
else :
$rating = sprintf("%s세 이상 관람가", $programdata['rating']);
endif;
if($GLOBALS['addverbose'] == 'y') :
$desc = $programName;
if($subprogramName) $desc = $desc."\n부제 : ".$subprogramName;
if($rebroadcast == True && $GLOBALS['addrebroadcast'] == 'y') $desc = $desc."\n방송 : 재방송";
if($episode) $desc = $desc."\n회차 : ".$episode."";
if($category) $desc = $desc."\n장르 : ".$category;
if($actors) $desc = $desc."\n출연 : ".trim($actors);
if($producers) $desc = $desc."\n제작 : ".trim($producers);
$desc = $desc."\n등급 : ".$rating;
else:
$desc = "";
endif;
if($programdata['desc']) $desc = $desc."\n".htmlspecialchars($programdata['desc'], ENT_XML1);
$desc = preg_replace('/ +/', ' ', $desc);
$contentTypeDict = array(
'교양' => 'Arts / Culture (without music)',
'만화' => 'Cartoons / Puppets',
'교육' => 'Education / Science / Factual topics',
'취미' => 'Leisure hobbies',
'드라마' => 'Movie / Drama',
'영화' => 'Movie / Drama',
'음악' => 'Music / Ballet / Dance',
'뉴스' => 'News / Current affairs',
'다큐' => 'Documentary',
'라이프' => 'Documentary',
'시사/다큐' => 'Documentary',
'연예' => 'Show / Game show',
'스포츠' => 'Sports',
'홈쇼핑' => 'Advertisement / Shopping'
);
$contentType = "";
foreach($contentTypeDict as $key => $value) :
if(!(strpos($category, $key) === False)) :
$contentType = $value;
endif;
endforeach;
fprintf($fp, " <programme start=\"%s +0900\" stop=\"%s +0900\" channel=\"%s\">\n", $startTime, $endTime, $ChannelId);
fprintf($fp, " <title lang=\"kr\">%s</title>\n", $programName);
if($subprogramName) :
fprintf($fp, " <sub-title lang=\"kr\">%s</sub-title>\n", $subprogramName);
endif;
if($GLOBALS['addverbose']=='y') :
fprintf($fp, " <desc lang=\"kr\">%s</desc>\n", $desc);
if($actors || $producers):
fprintf($fp, " <credits>\n");
if($actors) :
foreach(explode(',', $actors) as $actor):
if(trim($actor)) fprintf($fp, " <actor>%s</actor>\n", trim($actor));
endforeach;
endif;
if($producers) :
foreach(explode(',', $producers) as $producer):
if(trim($producer)) fprintf($fp, " <producer>%s</producer>\n", trim($producer));
endforeach;
endif;
fprintf($fp, " </credits>\n");
endif;
endif;
if($category) fprintf($fp, " <category lang=\"kr\">%s</category>\n", $category);
if($contentType) fprintf($fp, " <category lang=\"en\">%s</category>\n", $contentType);
if($episode && $GLOBALS['addxmltvns']=='y') fprintf($fp, " <episode-num system=\"xmltv_ns\">%s</episode-num>\n", $episode_ns);
if($episode && $GLOBALS['addxmltvns']!='y') fprintf($fp, " <episode-num system=\"onscreen\">%s</episode-num>\n", $episode_on);
if($rebroadcast) fprintf($fp, " <previously-shown />\n");
if($rating) :
fprintf($fp, " <rating system=\"KMRB\">\n");
fprintf($fp, " <value>%s</value>\n", $rating);
fprintf($fp, " </rating>\n");
endif;
fprintf($fp, " </programme>\n");
}
function getWeb($url, $params, $method) {
$ch = curl_init();
if($method == "GET"):
$url = $url."?".$params;
elseif($method == "POST"):
curl_setopt ($ch, CURLOPT_POST, True);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $params);
endif;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, True);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $GLOBALS['timeout']);
curl_setopt($ch, CURLOPT_HEADER, False);
curl_setopt($ch, CURLOPT_FAILONERROR, True);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['ua']);
$response = curl_exec($ch);
if(curl_error($ch) && $GLOBALS['debug']) printError($url." ".curl_error($ch));
curl_close($ch);
return $response;
}
function printLog($string) {
if(php_sapi_name() == "cli"):
fwrite(STDERR, $string."\n");
else:
header("Content-Type: text/plain; charset=utf-8");
print($string."\n");
endif;
}
function printError($string) {
if(php_sapi_name() == "cli"):
fwrite(STDERR, "Error : ".$string."\n");
else:
header("Content-Type: text/plain; charset=utf-8");
print("Error : ".$string."\n");
endif;
}
function _microtime() {
list($usec, $sec) = explode(" ", microtime());
return ($sec.(int)($usec*1000));
}
function startsWith($haystack, $needle) {
return !strncmp($haystack, $needle, strlen($needle));
}
function converthtmlspecialchars($match) {
return '<p class="cont">'.htmlspecialchars($match[1]);
}
//사용방법
$usage = <<<USAGE
usage: epg2xml.py [-h] [-i {ALL,KT,LG,SK}] [-v | -d | -o [xmltv.xml] | -s
[xmltv.sock]] [--icon http://www.example.com/icon] [-l 1-2]
[--rebroadcast y, n] [--episode y, n] [--verbose y, n]
USAGE;
//도움말
$help = <<<HELP
usage: epg2xml.php [-h] [-i {ALL,KT,LG,SK}]
[-v | -d | -o [xmltv.xml]
| -s [xmltv.sock]] [--icon http://www.example.com/icon]
[-l 1-2] [--rebroadcast y, n] [--episode y, n]
[--verbose y, n]
EPG 정보를 출력하는 방법을 선택한다
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-d, --display EPG 정보 화면출력
-o [xmltv.xml], --outfile [xmltv.xml]
EPG 정보 저장
-s [xmltv.sock], --socket [xmltv.sock]
xmltv.sock(External: XMLTV) EPG정보 전송
IPTV 선택
-i {ALL,KT,LG,SK} 사용하는 IPTV : ALL, KT, LG, SK
추가옵션:
--icon http://www.example.com/icon
채널 아이콘 URL, 기본값:
-l 1-2, --limit 1-2 EPG 정보를 가져올 기간, 기본값: 2
--rebroadcast y, n 제목에 재방송 정보 출력
--episode y, n 제목에 회차 정보 출력
--verbose y, n EPG 정보 추가 출력
HELP;
?>

View File

@ -1,31 +0,0 @@
{
"###_COMMENT_###" : "",
"###_COMMENT_###" : "epg 정보를 가져오는 설정 파일",
"###_COMMENT_###" : "사용하는 ISP 선택 (ALL, KT, LG, SK)",
"MyISP": "ALL",
"###_COMMENT_###" : "### # My Channel EPG 정보 가져오는 채널 ID ###",
"###_COMMENT_###" : "### 채널 ID를 , 로 구분하여 입력 ###",
"MyChannels" : "60, 110, 111, 122, 164",
"###_COMMENT_###" : "output 셋팅은 (d, o, s) 셋중에 하나로 선택한다",
"###_COMMENT_###" : " d - EPG 정보 화면 출력",
"###_COMMENT_###" : " o - EPG 정보 파일로 저장",
"###_COMMENT_###" : " s - EPG 정보 소켓으로 출력",
"output": "d",
"###_COMMENT_###" : "### TV channel icon url (ex : http://www.example.com/Channels) ###",
"default_icon_url": "",
"###_COMMENT_###" : "### 제목에 재방송 정보 출력 ###",
"default_rebroadcast": "n",
"###_COMMENT_###" : "#### 제목에 회차정보 출력 ###",
"default_episode" : "y",
"###_COMMENT_###" : "### EPG 정보 추가 출력 ###",
"default_verbose" : "y",
"###_COMMENT_###" : "### XMLTV_NS 정보 추가 출력 ###",
"default_xmltvns" : "n",
"###_COMMENT_###" : "### epg 데이터 가져오는 기간으로 1에서 7까지 설정가능 ###",
"default_fetch_limit" : "2",
"###_COMMENT_###" : "### epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) ###",
"default_xml_file" : "xmltv.xml",
"###_COMMENT_###" : "### # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) ###",
"default_xml_socket" : "xmltv.sock",
"###_COMMENT_###" : ""
}

View File

@ -1,4 +0,0 @@
#!/usr/bin/env php
<?php
include __DIR__."/epg2xml-web.php";
?>

View File

@ -1,652 +0,0 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from __future__ import print_function
import imp
import os
import sys
import json
import locale
import datetime
import codecs
import socket
import re
from xml.sax.saxutils import escape, unescape
import argparse
import pprint
from functools import partial
import time
try:
imp.find_module('bs4')
from bs4 import BeautifulSoup, SoupStrainer
except ImportError:
print("Error : ", "BeautifulSoup 모듈이 설치되지 않았습니다.", file=sys.stderr)
sys.exit()
try:
imp.find_module('lxml')
from lxml import html
except ImportError:
print("Error : ", "lxml 모듈이 설치되지 않았습니다.", file=sys.stderr)
sys.exit()
try:
imp.find_module('requests')
import requests
except ImportError:
print("Error : ", "requests 모듈이 설치되지 않았습니다.", file=sys.stderr)
sys.exit()
reload(sys)
sys.setdefaultencoding('utf-8')
if not sys.version_info[:2] == (2, 7):
print("Error : ", "python 2.7 버전이 필요합니다.", file=sys.stderr)
sys.exit()
# Set variable
__version__ = '1.2.6'
debug = False
today = datetime.date.today()
ua = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116'}
timeout = 5
htmlparser = 'lxml'
CHANNEL_ERROR = ' 존재하지 않는 채널입니다.'
CONTENT_ERROR = ' EPG 정보가 없습니다.'
HTTP_ERROR = ' EPG 정보를 가져오는데 문제가 있습니다.'
SOCKET_ERROR = 'xmltv.sock 파일을 찾을 수 없습니다.'
JSON_FILE_ERROR = 'json 파일을 읽을 수 없습니다.'
JSON_SYNTAX_ERROR = 'json 파일 형식이 잘못되었습니다.'
# Get epg data
def getEpg():
Channelfile = os.path.dirname(os.path.abspath(__file__)) + '/Channel.json'
ChannelInfos = []
try:
with open(Channelfile) as f: # Read Channel Information file
Channeldatajson = json.load(f)
except EnvironmentError:
printError("Channel." + JSON_FILE_ERROR)
sys.exit()
except ValueError:
printError("Channel." + JSON_SYNTAX_ERROR)
sys.exit()
print('<?xml version="1.0" encoding="UTF-8"?>')
print('<!DOCTYPE tv SYSTEM "xmltv.dtd">\n')
print('<tv generator-info-name="epg2xml ' + __version__ + '">')
# My Channel 정의
MyChannelInfo = []
if MyChannels :
for MyChannel in MyChannels.split(','):
MyChannelInfo.append(int(MyChannel.strip()))
for Channeldata in Channeldatajson: #Get Channel & Print Channel info
if Channeldata['Id'] in MyChannelInfo:
ChannelId = Channeldata['Id']
ChannelName = escape(Channeldata['Name'])
ChannelSource = Channeldata['Source']
ChannelServiceId = Channeldata['ServiceId']
ChannelIconUrl = escape(Channeldata['Icon_url'])
if MyISP != "ALL" and Channeldata[MyISP+'Ch'] is not None:
ChannelInfos.append([ChannelId, ChannelName, ChannelSource, ChannelServiceId])
ChannelNumber = str(Channeldata[MyISP+'Ch']);
ChannelISPName = escape(Channeldata[MyISP+' Name'])
print(' <channel id="%s">' % (ChannelId))
print(' <display-name>%s</display-name>' % (ChannelName))
print(' <display-name>%s</display-name>' % (ChannelISPName))
print(' <display-name>%s</display-name>' % (ChannelNumber))
print(' <display-name>%s</display-name>' % (ChannelNumber+' '+ChannelISPName))
if IconUrl:
print(' <icon src="%s/%s.png" />' % (IconUrl, ChannelId))
else :
print(' <icon src="%s" />' % (ChannelIconUrl))
print(' </channel>')
elif MyISP == "ALL":
ChannelInfos.append([ChannelId, ChannelName, ChannelSource, ChannelServiceId])
print(' <channel id="%s">' % (ChannelId))
print(' <display-name>%s</display-name>' % (ChannelName))
if IconUrl:
print(' <icon src="%s/%s.png" />' % (IconUrl, ChannelId))
else :
print(' <icon src="%s" />' % (ChannelIconUrl))
print(' </channel>')
# Print Program Information
for ChannelInfo in ChannelInfos:
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ChannelSource = ChannelInfo[2]
ChannelServiceId = ChannelInfo[3]
if(debug) : printLog(ChannelName + ' 채널 EPG 데이터를 가져오고 있습니다')
if ChannelSource == 'KT':
GetEPGFromKT(ChannelInfo)
elif ChannelSource == 'LG':
GetEPGFromLG(ChannelInfo)
elif ChannelSource == 'SK':
GetEPGFromSK(ChannelInfo)
elif ChannelSource == 'SKB':
GetEPGFromSKB(ChannelInfo)
elif ChannelSource == 'NAVER':
GetEPGFromNaver(ChannelInfo)
print('</tv>')
# Get EPG data from KT
def GetEPGFromKT(ChannelInfo):
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ServiceId = ChannelInfo[3]
epginfo = []
url = 'http://tv.kt.com/tv/channel/pSchedule.asp'
for k in range(period):
day = today + datetime.timedelta(days=k)
params = {'ch_type':'1', 'view_type':'1', 'service_ch_no':ServiceId, 'seldate':day.strftime('%Y%m%d')}
try:
response = requests.post(url, data=params, headers=ua, timeout=timeout)
response.raise_for_status()
html_data = response.content
data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore')
strainer = SoupStrainer('tbody')
soup = BeautifulSoup(data, htmlparser, parse_only=strainer, from_encoding='utf-8')
html = soup.find_all('tr') if soup.find('tbody') else ''
if(html):
for row in html:
for cell in [row.find_all('td')]:
startTime = endTime = programName = subprogramName = desc = actors = producers = category = episode = ''
rebroadcast = False
for minute, program, category in zip(cell[1].find_all('p'), cell[2].find_all('p'), cell[3].find_all('p')):
startTime = str(day) + ' ' + cell[0].text.strip() + ':' + minute.text.strip()
startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M')
startTime = startTime.strftime('%Y%m%d%H%M%S')
programName = program.text.replace('방송중 ', '').strip()
category = category.text.strip()
for image in [program.find_all('img', alt=True)]:
rating = 0
grade = re.match('([\d,]+)',image[0]['alt'])
if not (grade is None): rating = int(grade.group(1))
else: rating = 0
#ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
epginfo.append([ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating])
time.sleep(0.001)
else:
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
except (requests.exceptions.RequestException) as e:
if(debug): printError(ChannelName + str(e))
else: pass
if(epginfo) :
epgzip(epginfo)
# Get EPG data from LG
def GetEPGFromLG(ChannelInfo):
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ServiceId = ChannelInfo[3]
epginfo = []
url = 'http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi'
for k in range(period):
day = today + datetime.timedelta(days=k)
params = {'chnlCd': ServiceId, 'evntCmpYmd': day.strftime('%Y%m%d')}
try:
response = requests.post(url, data=params, headers=ua, timeout=timeout)
response.raise_for_status()
html_data = response.content
data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore')
data = data.replace('<재>', '&lt;재&gt;').replace(' [..','').replace(' (..', '')
strainer = SoupStrainer('table')
soup = BeautifulSoup(data, htmlparser, parse_only=strainer, from_encoding='utf-8')
html = soup.find('table').tbody.find_all('tr') if soup.find('table') else ''
if(html):
for row in html:
for cell in [row.find_all('td')]:
startTime = endTime = programName = subprogramName = desc = actors = producers = category = episode = ''
rebroadcast = False
rating = 0
startTime = str(day) + ' ' + cell[0].text
startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M')
startTime = startTime.strftime('%Y%m%d%H%M%S')
rating = 0 if cell[1].find('span', {'class': 'tag cte_all'}).text.strip()=="All" else int(cell[1].find('span', {'class': 'tag cte_all'}).text.strip())
cell[1].find('span', {'class': 'tagGroup'}).decompose()
pattern = '(<재>)?\s?(?:\[.*?\])?(.*?)(?:\[(.*)\])?\s?(?:\(([\d,]+)회\))?$'
matches = re.match(pattern, cell[1].text.strip().decode('string_escape'))
if not (matches is None):
programName = matches.group(2).strip() if matches.group(2) else ''
subprogramName = matches.group(3).strip() if matches.group(3) else ''
episode = matches.group(4) if matches.group(4) else ''
rebroadcast = True if matches.group(1) else False
category = cell[2].text.strip()
#ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
epginfo.append([ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating])
time.sleep(0.001)
else:
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
except (requests.exceptions.RequestException) as e:
if(debug): printError(ChannelName + str(e))
else: pass
if(epginfo) :
epgzip(epginfo)
# Get EPG data from SK
def GetEPGFromSK(ChannelInfo):
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ServiceId = ChannelInfo[3]
lastday = today + datetime.timedelta(days=period-1)
url = 'http://m.btvplus.co.kr/common/inc/IFGetData.do'
params = {'variable': 'IF_LIVECHART_DETAIL', 'pcode':'|^|start_time=' + today.strftime('%Y%m%d') + '00|^|end_time='+ lastday.strftime('%Y%m%d') + '24|^|svc_id=' + str(ServiceId)}
try:
response = requests.post(url, data=params, headers=ua, timeout=timeout)
response.raise_for_status()
json_data = response.text
try:
data = json.loads(json_data, encoding='utf-8')
if (data['channel'] is None) :
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
else :
programs = data['channel']['programs']
for program in programs:
startTime = endTime = programName = subprogramName = desc = actors = producers = category = episode = ''
rebroadcast = False
rating = 0
programName = program['programName'].replace('...', '>').encode('utf-8')
pattern = '^(.*?)(?:\s*[\(<]([\d,회]+)[\)>])?(?:\s*<([^<]*?)>)?(\((재)\))?$'
matches = re.match(pattern, programName)
if not (matches is None):
programName = matches.group(1).strip() if matches.group(1) else ''
subprogramName = matches.group(3).strip() if matches.group(3) else ''
episode = matches.group(2).replace('', '') if matches.group(2) else ''
episode = '' if episode== '0' else episode
rebroadcast = True if matches.group(5) else False
startTime = datetime.datetime.fromtimestamp(int(program['startTime'])/1000)
startTime = startTime.strftime('%Y%m%d%H%M%S')
endTime = datetime.datetime.fromtimestamp(int(program['endTime'])/1000)
endTime = endTime.strftime('%Y%m%d%H%M%S')
desc = program['synopsis'] if program['synopsis'] else ''
actors = program['actorName'].replace('...','').strip(', ') if program['actorName'] else ''
producers = program['directorName'].replace('...','').strip(', ') if program['directorName'] else ''
if not (program['mainGenreName'] is None) :
category = program['mainGenreName']
rating = int(program['ratingCd']) if program['ratingCd'] else 0
programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating}
writeProgram(programdata)
time.sleep(0.001)
except ValueError:
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
except (requests.exceptions.RequestException) as e:
if(debug): printError(ChannelName + str(e))
else: pass
#Get EPG data from SKB
def GetEPGFromSKB(ChannelInfo):
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ServiceId = ChannelInfo[3]
url = 'http://m.skbroadband.com/content/realtime/Channel_List.do'
epginfo = []
for k in range(period):
day = today + datetime.timedelta(days=k)
params = {'key_depth2': ServiceId, 'key_depth3': day.strftime('%Y%m%d')}
try:
response = requests.get(url, params=params, headers=ua, timeout=timeout)
response.raise_for_status()
html_data = response.content
data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore')
data = re.sub('EUC-KR', 'utf-8', data)
data = re.sub('<!--(.*?)-->', '', data, 0, re.I|re.S)
data = re.sub('<span class="round_flag flag02">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag03">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag04">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag09">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag10">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag11">(.*?)</span>', '', data)
data = re.sub('<span class="round_flag flag12">(.*?)</span>', '', data)
data = re.sub('<strong class="hide">프로그램 안내</strong>', '', data)
data = re.sub('<p class="cont">(.*)', partial(replacement, tag='p') , data)
data = re.sub('<p class="tit">(.*)', partial(replacement, tag='p') , data)
strainer = SoupStrainer('div', {'id':'uiScheduleTabContent'})
soup = BeautifulSoup(data, htmlparser, parse_only=strainer, from_encoding='utf-8')
html = soup.find_all('li',{'class':'list'}) if soup.find_all('li') else ''
if(html):
for row in html:
startTime = endTime = programName = subprogramName = desc = actors = producers = category = episode = ''
rebroadcast = False
rating = 0
startTime = str(day) + ' ' + row.find('p', {'class':'time'}).text
startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M')
startTime = startTime.strftime('%Y%m%d%H%M%S')
cell = row.find('p', {'class':'cont'})
grade = row.find('i', {'class':'hide'})
if not(grade is None) :
rating = int(grade.text.decode('string_escape').replace('세 이상','').strip())
if(cell):
if cell.find('span'):
cell.span.decompose()
cell = cell.text.decode('string_escape').strip()
pattern = "^(.*?)(\(([\d,]+)회\))?(<(.*)>)?(\((재)\))?$"
matches = re.match(pattern, cell)
if not(matches is None) :
programName = matches.group(1) if matches.group(1) else ''
subprogramName = matches.group(5) if matches.group(5) else ''
rebroadcast = True if matches.group(7) else False
episode = matches.group(3) if matches.group(3) else ''
#ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
epginfo.append([ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating])
time.sleep(0.001)
else:
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
except (requests.exceptions.RequestException) as e:
if(debug): printError(ChannelName + str(e))
else: pass
if(epginfo) :
epgzip(epginfo)
# Get EPG data from Naver
def GetEPGFromNaver(ChannelInfo):
ChannelId = ChannelInfo[0]
ChannelName = ChannelInfo[1]
ServiceId = ChannelInfo[3]
epginfo = []
totaldate = []
url = 'https://search.naver.com/p/csearch/content/batchrender_ssl.nhn'
for k in range(period):
day = today + datetime.timedelta(days=k)
totaldate.append(day.strftime('%Y%m%d'))
params = {'_callback': 'epg', 'fileKey': 'single_schedule_channel_day', 'pkid': '66', 'u1': 'single_schedule_channel_day', 'u2': ','.join(totaldate), 'u3': today.strftime('%Y%m%d'), 'u4': period, 'u5': ServiceId, 'u6': '1', 'u7': ChannelName + '편성표', 'u8': ChannelName + '편성표', 'where': 'nexearch'}
try:
response = requests.get(url, params=params, headers=ua, timeout=timeout)
response.raise_for_status()
json_data = re.sub(re.compile("/\*.*?\*/",re.DOTALL ) ,"" ,response.text.split("epg(")[1].strip(");").strip())
try:
data = json.loads(json_data, encoding='utf-8')
for i, date in enumerate(data['displayDates']):
for j in range(0,24):
for program in data['schedules'][j][i]:
startTime = endTime = programName = subprogramName = desc = actors = producers = category = episode = ''
rebroadcast = False
rating = 0
programName = unescape(program['title'])
startTime = date['date'] + ' ' + program['startTime']
startTime = datetime.datetime.strptime(startTime, '%Y%m%d %H:%M')
startTime = startTime.strftime('%Y%m%d%H%M%S')
episode = program['episode'].replace('','')
rebroadcast = program['isRerun']
rating = program['grade']
#ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating
epginfo.append([ChannelId, startTime, programName, subprogramName, desc, actors, producers, category, episode, rebroadcast, rating])
time.sleep(0.001)
except ValueError:
if(debug): printError(ChannelName + CONTENT_ERROR)
else: pass
except (requests.RequestException) as e:
if(debug): printError(ChannelName + str(e))
else: pass
if(epginfo) :
epgzip(epginfo)
# Zip epginfo
def epgzip(epginfo):
epginfo = iter(epginfo)
epg1 = next(epginfo)
for epg2 in epginfo:
programdata = {}
ChannelId = epg1[0]
startTime = epg1[1] if epg1[1] else ''
endTime = epg2[1] if epg2[1] else ''
programName = epg1[2] if epg1[2] else ''
subprogramName = epg1[3] if epg1[3] else ''
desc = epg1[4] if epg1[4] else ''
actors = epg1[5] if epg1[5] else ''
producers = epg1[6] if epg1[6] else ''
category = epg1[7] if epg1[7] else ''
episode = epg1[8] if epg1[8] else ''
rebroadcast = True if epg1[9] else False
rating = int(epg1[10]) if epg1[10] else 0
programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating}
writeProgram(programdata)
epg1 = epg2
# Write Program
def writeProgram(programdata):
ChannelId = programdata['channelId']
startTime = programdata['startTime']
endTime = programdata['endTime']
programName = escape(programdata['programName']).strip()
subprogramName = escape(programdata['subprogramName']).strip()
matches = re.match('(.*) \(?(\d+부)\)?', unescape(programName.encode('utf-8', 'ignore')))
if not(matches is None):
programName = escape(matches.group(1)).strip();
subprogramName = escape(matches.group(2)) + ' ' + subprogramName
subprogramName = subprogramName.strip()
if programName is None:
programName = subprogramName
actors = escape(programdata['actors'])
producers = escape(programdata['producers'])
category = escape(programdata['category'])
episode = programdata['episode']
if episode:
try:
episode_ns = int(episode) - 1
episode_ns = '0'+ '.' + str(episode_ns) + '.' + '0' + '/' + '0'
except ValueError as ex:
episode_ns = int(episode.split(',', 1)[0]) - 1
episode_ns = '0'+ '.' + str(episode_ns) + '.' + '0' + '/' + '0'
episode_on = episode
rebroadcast = programdata['rebroadcast']
if episode and addepisode == 'y': programName = programName + ' ('+ str(episode) + '회)'
if rebroadcast == True and addrebroadcast == 'y' : programName = programName + ' (재)'
if programdata['rating'] == 0 :
rating = '전체 관람가'
else :
rating = '%s세 이상 관람가' % (programdata['rating'])
if addverbose == 'y':
desc = programName
if subprogramName : desc = desc + '\n부제 : ' + subprogramName
if rebroadcast == True and addrebroadcast == 'y' : desc = desc + '\n방송 : 재방송'
if episode : desc = desc + '\n회차 : ' + str(episode) + ''
if category : desc = desc + '\n장르 : ' + category
if actors : desc = desc + '\n출연 : ' + actors.strip()
if producers : desc = desc + '\n제작 : ' + producers.strip()
desc = desc + '\n등급 : ' + rating
else:
desc =''
if programdata['desc'] : desc = desc + '\n' + escape(programdata['desc'])
desc = re.sub(' +',' ', desc)
contentTypeDict={'교양':'Arts / Culture (without music)', '만화':'Cartoons / Puppets', '교육':'Education / Science / Factual topics', '취미':'Leisure hobbies', '드라마':'Movie / Drama', '영화':'Movie / Drama', '음악':'Music / Ballet / Dance', '뉴스':'News / Current affairs', '다큐':'Documentary', '라이프':'Documentary', '시사/다큐':'Documentary', '연예':'Show / Game show', '스포츠':'Sports', '홈쇼핑':'Advertisement / Shopping'}
contentType = ''
for key, value in contentTypeDict.iteritems():
if key in category:
contentType = value
print(' <programme start="%s +0900" stop="%s +0900" channel="%s">' % (startTime, endTime, ChannelId))
print(' <title lang="kr">%s</title>' % (programName))
if subprogramName :
print(' <sub-title lang="kr">%s</sub-title>' % (subprogramName))
if addverbose=='y' :
print(' <desc lang="kr">%s</desc>' % (desc))
if actors or producers:
print(' <credits>')
if actors:
for actor in actors.split(','):
if actor.strip(): print(' <actor>%s</actor>' % (actor.strip()))
if producers:
for producer in producers.split(','):
if producer.strip(): print(' <producer>%s</producer>' % (producer).strip())
print(' </credits>')
if category: print(' <category lang="kr">%s</category>' % (category))
if contentType: print(' <category lang="en">%s</category>' % (contentType))
if episode and addxmltvns == 'y' : print(' <episode-num system="xmltv_ns">%s</episode-num>' % (episode_ns))
if episode and addxmltvns != 'y' : print(' <episode-num system="onscreen">%s</episode-num>' % (episode_on))
if rebroadcast: print(' <previously-shown />')
if rating:
print(' <rating system="KMRB">')
print(' <value>%s</value>' % (rating))
print(' </rating>')
print(' </programme>')
def printLog(*args):
print(*args, file=sys.stderr)
def printError(*args):
print("Error : ", *args, file=sys.stderr)
def replacement(match, tag):
if not(match is None):
tag = tag.strip()
programName = unescape(match.group(1)).replace('<','&lt;').replace('>','&gt;').strip()
programName = '<'+ tag + ' class="cont">' + programName
return programName
else:
return '';
Settingfile = os.path.dirname(os.path.abspath(__file__)) + '/epg2xml.json'
ChannelInfos = []
try:
with open(Settingfile) as f: # Read Channel Information file
Settings = json.load(f)
MyISP = Settings['MyISP'] if 'MyISP' in Settings else 'ALL'
MyChannels = Settings['MyChannels'] if 'MyChannels' in Settings else ''
default_output = Settings['output'] if 'output' in Settings else 'd'
default_xml_file = Settings['default_xml_file'] if 'default_xml_file' in Settings else 'xmltv.xml'
default_xml_socket = Settings['default_xml_socket'] if 'default_xml_socket' in Settings else 'xmltv.sock'
default_icon_url = Settings['default_icon_url'] if 'default_icon_url' in Settings else None
default_fetch_limit = Settings['default_fetch_limit'] if 'default_fetch_limit' in Settings else '2'
default_rebroadcast = Settings['default_rebroadcast'] if 'default_rebroadcast' in Settings else 'y'
default_episode = Settings['default_episode'] if 'default_episode' in Settings else 'y'
default_verbose = Settings['default_verbose'] if 'default_verbose' in Settings else 'n'
default_xmltvns = Settings['default_xmltvns'] if 'default_xmltvns' in Settings else 'n'
except EnvironmentError:
printError("epg2xml." + JSON_FILE_ERROR)
sys.exit()
except ValueError:
printError("epg2xml." + JSON_SYNTAX_ERROR)
sys.exit()
parser = argparse.ArgumentParser(description = 'EPG 정보를 출력하는 방법을 선택한다')
argu1 = parser.add_argument_group(description = 'IPTV 선택')
argu1.add_argument('-i', dest = 'MyISP', choices = ['ALL', 'KT', 'LG', 'SK'], help = '사용하는 IPTV : ALL, KT, LG, SK', default = MyISP)
argu2 = parser.add_mutually_exclusive_group()
argu2.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__)
argu2.add_argument('-d', '--display', action = 'store_true', help = 'EPG 정보 화면출력')
argu2.add_argument('-o', '--outfile', metavar = default_xml_file, nargs = '?', const = default_xml_file, help = 'EPG 정보 저장')
argu2.add_argument('-s', '--socket', metavar = default_xml_socket, nargs = '?', const = default_xml_socket, help = 'xmltv.sock(External: XMLTV)로 EPG정보 전송')
argu3 = parser.add_argument_group('추가옵션')
argu3.add_argument('--icon', dest = 'icon', metavar = "http://www.example.com/icon", help = '채널 아이콘 URL, 기본값: '+ default_icon_url, default = default_icon_url)
argu3.add_argument('-l', '--limit', dest = 'limit', type=int, metavar = "1-7", choices = range(1,8), help = 'EPG 정보를 가져올 기간, 기본값: '+ str(default_fetch_limit), default = default_fetch_limit)
argu3.add_argument('--rebroadcast', dest = 'rebroadcast', metavar = 'y, n', choices = 'yn', help = '제목에 재방송 정보 출력', default = default_rebroadcast)
argu3.add_argument('--episode', dest = 'episode', metavar = 'y, n', choices = 'yn', help = '제목에 회차 정보 출력', default = default_episode)
argu3.add_argument('--verbose', dest = 'verbose', metavar = 'y, n', choices = 'yn', help = 'EPG 정보 추가 출력', default = default_verbose)
args = parser.parse_args()
if args.MyISP : MyISP = args.MyISP
if args.display :
default_output = "d"
elif args.outfile :
default_output = "o"
default_xml_file = args.outfile
elif args.socket :
default_output = "s"
default_xml_socket = args.socket
if args.icon : default_icon_url = args.icon
if args.limit : default_fetch_limit = args.limit
if args.rebroadcast : default_rebroadcast = args.rebroadcast
if args.episode : default_episode = args.episode
if args.verbose : default_verbose = args.verbose
if MyISP:
if not any(MyISP in s for s in ['ALL', 'KT', 'LG', 'SK']):
printError("MyISP는 ALL, KT, LG, SK만 가능합니다.")
sys.exit()
else :
printError("epg2xml.json 파일의 MyISP항목이 없습니다.")
sys.exit()
if default_output :
if any(default_output in s for s in ['d', 'o', 's']):
if default_output == "d" :
output = "display";
elif default_output == "o" :
output = "file";
elif default_output == 's' :
output = "socket";
else :
printError("default_output는 d, o, s만 가능합니다.")
sys.exit()
else :
printError("epg2xml.json 파일의 output항목이 없습니다.");
sys.exit()
IconUrl = default_icon_url
if default_rebroadcast :
if not any(default_rebroadcast in s for s in ['y', 'n']):
printError("default_rebroadcast는 y, n만 가능합니다.")
sys.exit()
else :
addrebroadcast = default_rebroadcast
else :
printError("epg2xml.json 파일의 default_rebroadcast항목이 없습니다.");
sys.exit()
if default_episode :
if not any(default_episode in s for s in ['y', 'n']):
printError("default_episode는 y, n만 가능합니다.")
sys.exit()
else :
addepisode = default_episode
else :
printError("epg2xml.json 파일의 default_episode항목이 없습니다.");
sys.exit()
if default_verbose :
if not any(default_verbose in s for s in ['y', 'n']):
printError("default_verbose는 y, n만 가능합니다.")
sys.exit()
else :
addverbose = default_verbose
else :
printError("epg2xml.json 파일의 default_verbose항목이 없습니다.");
sys.exit()
if default_xmltvns :
if not any(default_xmltvns in s for s in ['y', 'n']):
printError("default_xmltvns는 y, n만 가능합니다.")
sys.exit()
else :
addxmltvns = default_xmltvns
else :
printError("epg2xml.json 파일의 default_verbose항목이 없습니다.");
sys.exit()
if default_fetch_limit :
if not any(str(default_fetch_limit) in s for s in ['1', '2', '3', '4', '5', '6', '7']):
printError("default_fetch_limit 는 1, 2, 3, 4, 5, 6, 7만 가능합니다.")
sys.exit()
else :
period = int(default_fetch_limit)
else :
printError("epg2xml.json 파일의 default_fetch_limit항목이 없습니다.");
sys.exit()
if output == "file" :
if default_xml_file :
sys.stdout = codecs.open(default_xml_file, 'w+', encoding='utf-8')
else :
printError("epg2xml.json 파일의 default_xml_file항목이 없습니다.");
sys.exit()
elif output == "socket" :
if default_xml_socket :
try:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(default_xml_socket)
sockfile = sock.makefile('w+')
sys.stdout = sockfile
except socket.error:
printError(SOCKET_ERROR)
sys.exit()
else :
printError("epg2xml.json 파일의 default_xml_socket항목이 없습니다.");
sys.exit()
getEpg()