Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 110 lines (91 sloc) 3.572 kB
cc9af55 @ngokevin renamed to soundcloud-dl, fixed shebang
authored
1 #!/usr/bin/python
4a4b13d @ngokevin initial commit, can't get cookies out
authored
2 from optparse import OptionParser
89f85a0 @ngokevin finish. now successfully downloads .mp3 files and saves it to file. n…
authored
3 import cookielib
4 import urllib2
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
5 import random
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
6 import sys
4a4b13d @ngokevin initial commit, can't get cookies out
authored
7 import re
cec546c @uberj someone forgot to test their code.
uberj authored
8 import time
4a4b13d @ngokevin initial commit, can't get cookies out
authored
9
aae03b4 @uberj Added random name generator. This will be usefull if you want random …
uberj authored
10 # Maximum number of download attempts
abe7339 @uberj Reworked how I implimented the error checking that was removed. There…
uberj authored
11 max_retry = 3
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
12
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
13 # set up header values and openers
14 header_values = {'User-Agent' : 'Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16', 'Accept' : 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 'Accept-Encoding' : 'gzip,deflate,sdch', 'Accept-Language' : 'en-US,en;q=0.8', 'Cache-Control' : 'max-age=0', 'Connection' : 'keep-alive'}
15 cj = cookielib.MozillaCookieJar()
16 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), urllib2.HTTPHandler())
17 urllib2.install_opener(opener)
18
19 def open_url(url):
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
20 tries = 0;
21 while tries < max_retry:
22 tries += 1
23 print "Fetching..."
c325916 @uberj Changes:
uberj authored
24 try:
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
25 request = urllib2.Request(options.url, headers=header_values)
c325916 @uberj Changes:
uberj authored
26 response = opener.open(request)
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
27 break
47ec6ce @uberj Carpet bombing exception handling is bad. You don't know if you have …
uberj authored
28 except urllib2.HTTPError, e:
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
29 time.sleep(tries)
47ec6ce @uberj Carpet bombing exception handling is bad. You don't know if you have …
uberj authored
30 except ValueError, e:
31 print str(e)
32 return None
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
33 print "Retrieved html"
47ec6ce @uberj Carpet bombing exception handling is bad. You don't know if you have …
uberj authored
34 html = response.read()
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
35 if not html:
36 print "failed to fetch url"
47ec6ce @uberj Carpet bombing exception handling is bad. You don't know if you have …
uberj authored
37 return None
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
38 return html
39
4a4b13d @ngokevin initial commit, can't get cookies out
authored
40 def get_stream_token_uid(page):
41 """ returns stream token and uid as tuple """
42 match = re.search('"uid":"([\w\d]+?)".*?stream_token=([\w\d]+)', page)
c325916 @uberj Changes:
uberj authored
43 if match:
4a4b13d @ngokevin initial commit, can't get cookies out
authored
44 uid = match.group(1)
45 stream_token = match.group(2)
46 return (uid, stream_token)
47
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
48 def get_song_title(page):
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
49 match = re.search('(?<=\"title\":\").*?(?=\")', page)
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
50 if match:
51 return match.group(0).replace(' ','_')
aae03b4 @uberj Added random name generator. This will be usefull if you want random …
uberj authored
52 else:
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
53 random_length = 5
54 return ''.join(random.choice(alpha) for i in xrange(random_length))
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
55
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
56 def download(uid, token, song_title):
89f85a0 @ngokevin finish. now successfully downloads .mp3 files and saves it to file. n…
authored
57 """ given url with token and uid, download file to mp3 """
58
c325916 @uberj Changes:
uberj authored
59 # compose a url with uid and token and request the mpeg
89f85a0 @ngokevin finish. now successfully downloads .mp3 files and saves it to file. n…
authored
60 url = "http://media.soundcloud.com/stream/%s?stream_token=%s" % (uid, token)
61 request = urllib2.Request(url, headers=header_values)
62 response = opener.open(request)
63
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
64 f = open(song_title, 'w')
89f85a0 @ngokevin finish. now successfully downloads .mp3 files and saves it to file. n…
authored
65 f.write(response.read())
66
67
4a4b13d @ngokevin initial commit, can't get cookies out
authored
68 if __name__ == '__main__':
69
70 parser = OptionParser()
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
71 parser.add_option("-u", "--url", help="soundcloud url to download", dest="url")
4a4b13d @ngokevin initial commit, can't get cookies out
authored
72 (options, args) = parser.parse_args()
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
73 if not options.url:
74 parser.error("--url option requires an argument")
c325916 @uberj Changes:
uberj authored
75
abe7339 @uberj Reworked how I implimented the error checking that was removed. There…
uberj authored
76 abort = True
77 error = ''
78 tries = 0
79 while tries < max_retry:
80 # open up initial page to get stream token, uid, song title
81 html = open_url(options.url)
82 if not html:
83 tries += 1
84 error = "Could not retrieve initial html."
85 continue # Try again
86 # Sometimes html isn't html, it's some flash applet (or something binary).
87 # In that case get_stream_token_uid returns None.
88 info = get_stream_token_uid(html)
89 if not info:
90 tries += 1
91 error = "Could not get stream token."
92 continue # Try again
93 (uid, token) = info
94
95 song_title = get_song_title(html) + '.mp3'
96 abort = False
97 break #Break out, we have all the info we need.
98
99 if abort:
100 print error
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
101 sys.exit(1)
b26a904 @ngokevin cleaned up the code, fixed typos, made sane default, and use random f…
authored
102
4a4b13d @ngokevin initial commit, can't get cookies out
authored
103
89f85a0 @ngokevin finish. now successfully downloads .mp3 files and saves it to file. n…
authored
104 # the browser does this...so we will too
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
105 open_url('http://media.soundcloud.com/crossdomain.xml')
4a4b13d @ngokevin initial commit, can't get cookies out
authored
106
48dbfb3 @ngokevin encapsulated soundcloud for usability. added some exception handling
authored
107 download(uid, token, song_title)
8e73c8d @uberj Re-introduced a whole bunch of error handling code. This is important…
uberj authored
108 print song_title+".mp3 has been downloaded."
4a4b13d @ngokevin initial commit, can't get cookies out
authored
109
Something went wrong with that request. Please try again.