#!/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_episodes(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: generator = choose(get_episodes(cid), 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..."