#!/usr/bin/env python3 # itv.py # Copyright (C) 2015 Jashandeep Sohi # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse from lxml import etree import requests import re from sys import stderr from os import path import subprocess LIVESTREAMER = "localhost:88" if __name__ == "__main__": arg_parser = argparse.ArgumentParser( description = "ITV downloader", ) arg_parser.add_argument( "url", help = "programme url", action = "store", ) arg_parser.add_argument( "filename", help = "output filename", action = "store", nargs = "?", ) arg_parser.add_argument( "-d", "--dir", help = "download directory (default: '%(default)s')", action = "store", default = ".", ) arg_parser.add_argument( "-s", "--start", help = "start at given time (default: '%(default)s')", action = "store", default = 0, type = int, ) arg_parser.add_argument( "-e", "--end", help = "end at given time (default: '%(default)s')", action = "store", default = -1, type = int, ) arg_parser.add_argument( "-p", "--proxy", help = "proxy address (e.g. 'http://2.13.1.2:1234', " "'socks://3.1.2.3:1234', etc)", action = "store", default = "" ) resume_group = arg_parser.add_mutually_exclusive_group() resume_group.add_argument( "-r", "--resume", help = "attempt to resume (set by default)", action = "store_true", default = True ) resume_group.add_argument( "-R", "--no-resume", help = "don't attempt to resume (overwrites old file)", action = "store_false", dest = "resume" ) args = arg_parser.parse_args() session = requests.Session() session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 5.1; rv:32.0) Gecko/20100101 " "Firefox/32.0", }) page_req = session.get(args.url) pid_match = re.search('data-video-id="(.*?)"', page_req.text) try: pid = pid_match.group(1).replace("\\", "") except: arg_parser.error("could not parse video pid from page") soap_msg1 = """ {pid} FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF itv.com Itv ITVPLAYER.12.18.4 None ITV Any ITVPLAYER.VIDEO DotCom ItvCom Big 2 """ soap_msg2=""" A26C4B97-C300-F83A-C5A6-2C0FD584D9B8 {pid} itv.com Itv 584e4d9a-fa89-4398-9033-f6ed4dead584 ITVPLAYER.2.18.10.+build.21057aabd9 None ITV Any ITVPLAYER.VIDEO DotCom ItvCom Big 2 """ if re.search("sim\d",pid): soap_msg = soap_msg2.format(pid = pid) is_live = True else: soap_msg = soap_msg1.format(pid = pid) is_live = False media_req = session.post( "http://mercury.itv.com/PlaylistService.svc", headers = { "Referer": "http://www.itv.com/mercury/Mercury_VideoPlayer.swf?v=1.6.479/[[DYNAMIC]]/2", "Content-type": "text/xml; charset=utf-8", "SOAPAction": "http://tempuri.org/PlaylistService/GetPlaylist" }, data = soap_msg, proxies = {"http": args.proxy} if args.proxy else None, timeout = 20 ) media_req_tree = etree.fromstring(media_req.text) #print media_req.text title = media_req_tree.xpath("//ProgrammeTitle/text()")[0] if media_req_tree.xpath("//ProgrammeTitle/text()") else "title" ep_title = media_req_tree.xpath("//EpisodeTitle/text()")[0] if media_req_tree.xpath("//EpisodeTitle/text()") else "episode" media_files = media_req_tree.xpath("//VideoEntries/Video/MediaFiles")[0] rtmp_url = media_files.xpath("@base")[0] media_file = media_files.xpath( "MediaFile[not(../MediaFile/@bitrate > @bitrate)]" )[0] bitrate = int(media_file.xpath("@bitrate")[0]) // 1000 rtmp_playpath = media_file.xpath("URL/text()")[0] file_path = path.join( args.dir, args.filename if args.filename else re.sub( "[\W_]+", "-", "-".join(map(str, filter(None, ( title, ep_title, bitrate, args.start, args.end if args.end > 0 else None )))) ).lower() + ".flv" ) print "http://%s/%s"%(LIVESTREAMER,rtmp_url), print "playpath="+rtmp_playpath, print "pageUrl="+args.url, if is_live: print "live", print "swfVfy="+"http://www.itv.com/mercury/Mercury_VideoPlayer.swf" cmd = [ "rtmpdump", "-r", rtmp_url, "--playpath", rtmp_playpath, "--pageUrl", args.url, "--swfVfy", "http://www.itv.com/mercury/Mercury_VideoPlayer.swf" "?v=1.6.479/[[DYNAMIC]]/2" "--flashVer", "WIN 15,0,0,189", "--flv", file_path, "--resume" if args.resume else "", "--start={}".format(args.start), "--stop={}".format(args.end) if args.end > 0 else "" ] url2 = "http://%s/%s playpath=%s pageUrl=%s swfVfy=http://www.itv.com/mercury/Mercury_VideoPlayer.swf%s"%(LIVESTREAMER,rtmp_url,rtmp_playpath,args.url," live" if is_live else "") cmd2 = [r"c:\Program Files\VideoLAN\VLC\vlc.exe",url2] if is_live: cmd.append("--live") #print cmd2 print url2 print '\nrtmpdump -r "%s" --playpath "%s" --pageUrl "%s" --swfVfy "http://www.itv.com/mercury/Mercury_VideoPlayer.swf"%s -o output.flv\n'%(rtmp_url,rtmp_playpath,args.url," live" if is_live else "") proc = subprocess.Popen(cmd2) try: proc.communicate() except KeyboardInterrupt: pass # vim: tabstop=2 expandtab