comparison iview.py @ 0:fa7ca67af8c9

Initial commit of a python program to fetch iview streams using flvstreamer.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 20 Aug 2009 16:48:16 +0930
parents
children f914f08d69f5
comparison
equal deleted inserted replaced
-1:000000000000 0:fa7ca67af8c9
1 #!/usr/bin/env python
2
3 import exceptions
4 import htmlentitydefs
5 import re
6 import sys
7 import time
8 import urllib2
9 import xml.dom.minidom as minidom
10 from xml.parsers.expat import ExpatError
11
12 confurl = 'http://www.abc.net.au/iview/iview_231_config.xml'
13
14 pattern = re.compile("&(\w+?);")
15
16 def descape_entity(m, defs=htmlentitydefs.entitydefs):
17 try:
18 return defs[m.group(1)]
19 except KeyError:
20 return m.group(0) # use as is
21 def descape(string):
22 return pattern.sub(descape_entity, string)
23
24 def toBool(s):
25 if type(s) is bool:
26 return s
27 s = str(s).strip().lower()
28 return not s[0] in ['f','n','0']
29
30 class NoAsset(exceptions.Exception):
31 pass
32
33 class Series(object):
34 def __init__(self, seriesElem):
35 self.id = seriesElem.getAttribute("id")
36 self.url = seriesElem.getAttribute("href")
37
38 # Fetch titles and so on
39 #print "Fetching series URL " + self.url
40 xmlp = minidom.parse(urllib2.urlopen(self.url))
41 self.title = self.gatherChildren(xmlp.getElementsByTagName("title"))
42 self.descr = self.gatherChildren(xmlp.getElementsByTagName("description"))
43
44 # No asset means unpublished?
45 assets = xmlp.getElementsByTagName("abc:videoAsset")
46 if len(assets) == 0:
47 raise NoAsset
48
49 self.asset = assets[0].childNodes[0].data.rstrip('.flv')
50
51 rating = xmlp.getElementsByTagName("abc:rating")[0].childNodes
52 if len(rating) > 0:
53 self.rating = descape(rating[0].data)
54 else:
55 self.rating = "unrated"
56
57 self.imgurl = xmlp.getElementsByTagName("image")[0].getElementsByTagName("url")[0].childNodes[0].data
58 self.expiry = time.strptime(xmlp.getElementsByTagName("abc:expireDate")[0].childNodes[0].data ,
59 '%d/%m/%Y %H:%M:%S')
60
61 def gatherChildren(self, elemList):
62 rtn = []
63 for e in elemList:
64 if len(e.childNodes) > 0:
65 rtn.append(descape(e.childNodes[0].data.strip()))
66 return rtn
67
68 class Channel(object):
69 def __init__(self, chanElem):
70 self.id = chanElem.getAttribute("id")
71 self.sort = chanElem.getAttribute("sort")
72 self.path = chanElem.getAttribute("path")
73 self.thumb = chanElem.getAttribute("thumb")
74 self.name = descape(chanElem.getElementsByTagName("name")[0].childNodes[0].data)
75 self.descr = descape(chanElem.getElementsByTagName("description")[0].childNodes[0].data)
76 self.series = []
77
78 def getSeries(self):
79 # This can take ages
80 print "Fetching series for channel " + self.name
81 # Series is nested for some reason
82 xmlp = minidom.parse(urllib2.urlopen(self.path))
83 nl = xmlp.getElementsByTagName("series")[0]
84 for s in nl.getElementsByTagName("series"):
85 try:
86 self.series.append(Series(s))
87 except ExpatError:
88 print "Unable to parse XML, skipping"
89 continue
90 except NoAsset:
91 print "No asset tag, skipping"
92 continue
93
94 class IView(object):
95 def __init__(self):
96 # Fetch and parse config URL
97 #print "Fetching configuration URL"
98 xmlp = minidom.parse(urllib2.urlopen(confurl))
99 self.params = {}
100 for param in xmlp.getElementsByTagName("param"):
101 self.params[param.getAttribute("name")] = param.getAttribute("value")
102
103 # Get token & metered status from auth_path URL
104 #print "Fetching authorisation information"
105 self.getAuth()
106
107 # Build channel list
108 #print "Fetching channel list"
109 xmlp = minidom.parse(urllib2.urlopen(self.params['base_url'] + '/' + self.params['xml_channels']))
110 self.channels = []
111 for chan in xmlp.getElementsByTagName("channel"):
112 self.channels.append(Channel(chan))
113
114 def getAuth(self):
115 xmlp = minidom.parse(urllib2.urlopen(self.params['auth_path']))
116 self.token = xmlp.getElementsByTagName("token")[0].childNodes[0].data
117 self.metered = not toBool(xmlp.getElementsByTagName("free")[0].childNodes[0].data)
118
119 server = xmlp.getElementsByTagName("server")[0].childNodes
120 if len(server) == 0:
121 self.rtmp = self.params['server_streaming'].rstrip('/ondemand') + '////' + self.params['media_path']
122 self.tcurl = self.params['server_streaming']
123 else:
124 self.rtmp = xmlp.getElementsByTagName("server")[0].childNodes[0].data
125 self.tcurl = None
126
127 def genFetchCmd(self, series, outfile):
128 cmd = ['-m', '1200']
129 if self.tcurl == None:
130 cmd += ['-r', self.rtmp + '?auth=' + self.token]
131 cmd += ['-y', series.asset]
132 else:
133 cmd += ['-r', self.rtmp + series.asset]
134 cmd += ['-t', self.tcurl + '?auth=' + self.token]
135 cmd += ['-o', outfile]
136 return cmd
137
138 # Non-metered:
139 #/home/darius/projects/flvstreamer/flvstreamer_x86
140 # -r rtmp://cp53909.edgefcs.net////flash/playback/_definst_/catch_up/compass_09_23_28
141 # -t rtmp://cp53909.edgefcs.net/ondemand?auth=daEbFbibab6d4c0cwdjcwcya4dTb9cucucw-bkJnTd-8-klt_rFzqL&aifp=v001
142 # -o ./compass_09_23_28.flv -m 1200