From: James Bunton Date: Mon, 18 Jul 2011 14:39:06 +0000 (+1000) Subject: Added ABC iView downloader X-Git-Url: https://code.delx.au/monosys/commitdiff_plain/d9ff643294192debd79c014709d59776c77e50cd Added ABC iView downloader --- diff --git a/scripts/iview-downloader b/scripts/iview-downloader new file mode 100755 index 0000000..1aa11fc --- /dev/null +++ b/scripts/iview-downloader @@ -0,0 +1,133 @@ +#!/usr/bin/env python + +import json +from lxml import etree +import signal +import subprocess +import urllib + +BASE_URL = "http://www.abc.net.au/iview/" +CONFIG_URL = BASE_URL + "xml/config.xml" +HASH_URL = BASE_URL + "images/iview.jpg" +NS = { + "auth": "http://www.abc.net.au/iView/Services/iViewHandshaker", +} + +def grab_xml(path): + f = urllib.urlopen(path) + doc = etree.parse(f) + f.close() + return doc + +def grab_json(path): + f = urllib.urlopen(path) + doc = json.load(f) + f.close() + return doc + +def choose(options, allow_multi): + skeys = sorted(options.keys()) + for i, key in enumerate(skeys): + print " %d) %s" % (i+1, key) + print " 0) Back" + while True: + try: + values = map(int, raw_input("Choose> ").split()) + if len(values) == 0: + continue + if 0 in values: + return + values = [options[skeys[value-1]] for value in values] + if allow_multi: + return values + else: + if len(values) == 1: + return values[0] + except ValueError: + pass + +def download_rtmp(filename, vbase, vpath): + cmd = [ + "rtmpdump", + "-o", filename, + "-r", vbase, + "-y", vpath, + "--swfVfy", HASH_URL, + ] + try: + p = subprocess.Popen(cmd) + p.wait() + except KeyboardInterrupt: + print "Cancelled", cmd + try: + p.terminate() + p.wait() + except KeyboardInterrupt: + p.send_signal(signal.SIGKILL) + p.wait() + +def download_video(title, vpath): + auth_doc = grab_xml(PARAMS["auth"]) + vbase = auth_doc.xpath("//auth:server/text()", namespaces=NS)[0] + token = auth_doc.xpath("//auth:token/text()", namespaces=NS)[0] + vbase += "?auth=" + token + vpath, ext = vpath.rsplit(".", 1) + vpath = ext + ":" + vpath + filename = title + "." + ext + download_rtmp(filename, vbase, vpath) + +def get_categories(): + categories_doc = grab_xml(BASE_URL + PARAMS["categories"]) + categories = {} + for category in categories_doc.xpath("//category[@genre='true']"): + cid = category.attrib["id"] + name = category.xpath("name/text()")[0] + categories[name] = cid + return categories + +def get_series(cid): + series_list_doc = grab_json(PARAMS["api"] + "seriesIndex") + episode_list = {} + for series in series_list_doc: + categories = series["e"].split() + if cid not in categories: + continue + sid = series["a"] + series_title = series["b"].replace("&", "&") + series_doc = grab_json(PARAMS["api"] + "series=" + sid)[0] + for episode in series_doc["f"]: + vpath = episode["n"] + episode_title = episode["b"].strip() + if series_title != episode_title: + episode_title = series_title + " " + episode_title + episode_list[episode_title] = (episode_title, vpath) + return episode_list + + + +def main(): + config_doc = grab_xml(CONFIG_URL) + global PARAMS + PARAMS = dict((p.attrib["name"], p.attrib["value"]) for p in config_doc.xpath("/config/param")) + + while True: + cid = choose(get_categories(), allow_multi=False) + if cid is None: + continue + while True: + sid = choose(get_series(cid), allow_multi=False) + if sid is None: + break + while True: + generator = choose(get_episodes(sid), allow_multi=True) + if generator is None: + break + for title, vpath in generator: + download_video(title, vpath) + +if __name__ == "__main__": + try: + main() + except (KeyboardInterrupt, EOFError): + print "\nExiting..." +