]>
code.delx.au - webdl/blob - plus7.py
5 from lxml
. cssselect
import CSSSelector
7 from common
import grab_html
, grab_json
, download_rtmp
, Node
9 BASE
= "http://au.tv.yahoo.com"
10 BROWSE
= BASE
+ "/plus7/browse/"
12 METADATA_BASE
= "http://video.query.yahoo.com/v1/public/yql?"
14 'q' : 'SELECT streams,status FROM yahoo.media.video.streams WHERE id=" %s " AND format="mp4,flv" AND protocol="rtmp,http" AND plrs=" %s " AND offnetwork="false" AND site="autv_plus7" AND lang="en-AU" AND region="AU" AND override="none";' ,
15 'callback' : 'jsonp_callback' ,
20 HASH_URL
= "http://d.yimg.com/m/up/ypp/au/player.swf"
23 def extract_and_remove ( tokens
, key
):
24 lowertokens
= [ x
. lower () for x
in tokens
]
25 pos
= lowertokens
. index ( key
)
27 value
= int ( tokens
[ pos
+ 1 ])
28 tokens
= tokens
[: pos
] + tokens
[ pos
+ 2 :]
33 def demangle_title ( title
, subtitle
):
34 tokens
= title
. split ()
35 insert_pos
= len ( tokens
)
38 tokens
+= [ "-" ] + subtitle
. split ()
41 season
, tokens
= extract_and_remove ( tokens
, "series" )
42 episode
, tokens
= extract_and_remove ( tokens
, "episode" )
43 if insert_pos
< len ( tokens
):
44 tokens
. insert ( insert_pos
, "-" )
45 tokens
. insert ( insert_pos
, " %sx%s " % ( season
, str ( episode
). zfill ( 2 )))
49 return " " . join ( tokens
)
51 class Plus7Node ( Node
):
52 def __init__ ( self
, title
, parent
, url
):
53 Node
.__ init
__ ( self
, title
, parent
)
55 self
. can_download
= True
57 def get_video_id ( self
):
58 doc
= grab_html ( self
. url
, 3600 )
59 for script
in doc
. xpath ( "//script" ):
62 for line
in script
. text
. split ( ";" ):
64 if line
. find ( "new Y.VideoPlatform.VideoPlayer" ) <= 0 :
67 ### vidparams = line[line.find("(")+1 : line.rfind(")")]
68 ### vidparams = json.loads(vidparams)
69 ### return vidparams["playlist"]["mediaItems"][0]["id"]
71 # Cannot parse it as JSON :(
72 pos1
= line
. find ( '"mediaItems":' )
75 pos2
= line
. find ( '"id":' , pos1
)
78 pos3
= line
. find ( '"' , pos2
+ 5 )
79 pos4
= line
. find ( '"' , pos2
+ 6 )
80 if pos3
< 0 or pos4
< 0 :
82 return line
[ pos3
+ 1 : pos4
]
84 raise Exception ( "Could not find video id on page " + self
. url
)
86 def generate_session ( self
):
87 return "" . join ([ random
. choice ( string
. ascii_letters
) for x
in xrange ( 22 )])
90 vid_id
= self
. get_video_id ()
91 qs
= dict ( METADATA_QUERY
. items ()) # copy..
92 qs
[ "q" ] = qs
[ "q" ] % ( vid_id
, self
. generate_session ())
93 url
= METADATA_BASE
+ urllib
. urlencode ( qs
)
94 doc
= grab_json ( url
, 0 , skip_function
= True )
95 stream_data
= doc
[ "query" ][ "results" ][ "mediaObj" ][ 0 ][ "streams" ][ 0 ]
96 vbase
= stream_data
[ "host" ]
97 vpath
= stream_data
[ "path" ]
98 filename
= self
. title
+ ".flv"
99 return download_rtmp ( filename
, vbase
, vpath
, HASH_URL
)
102 class Plus7Series ( Node
):
103 def __init__ ( self
, title
, parent
, url
):
104 Node
.__ init
__ ( self
, title
, parent
)
107 def fill_children ( self
):
108 doc
= grab_html ( self
. url
, 3600 )
109 for item
in CSSSelector ( "#related-episodes div.itemdetails" )( doc
):
110 title
= CSSSelector ( "span.title" )( item
)[ 0 ]. text
111 subtitle
= CSSSelector ( "span.subtitle" )( item
)[ 0 ]. xpath ( "string()" )
112 title
= demangle_title ( title
, subtitle
)
113 url
= CSSSelector ( "a" )( item
)[ 0 ]. attrib
[ "href" ]
114 Plus7Node ( title
, self
, BASE
+ url
)
116 class Plus7Root ( Node
):
117 def __init__ ( self
, parent
):
118 Node
.__ init
__ ( self
, "Yahoo Plus7 (broken!)" , parent
)
120 def fill_children ( self
):
121 doc
= grab_html ( BROWSE
, 3600 )
123 for script
in doc
. xpath ( "//script" ):
124 if not script
. text
or not script
. text
. startswith ( "var shows = " ):
126 shows
= script
. text
[ 12 :]
127 shows
= shows
. rstrip ( "; \n " )
128 shows
= json
. loads ( shows
)
130 Plus7Series ( show
[ "title" ], self
, show
[ "url" ])
132 def fill_nodes ( root_node
):