-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathYoutube playlist downloader.py
119 lines (95 loc) · 3.68 KB
/
Youtube playlist downloader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
# youtube-dl-playlist
#
# Utility to download Youtube playlist videos.
#
# @author Mehdi Alouane <[email protected]>
# @license LGPL version 2 or greater <http://www.gnu.org/licenses/lgpl.html>
import sys
import urllib
import httplib
import json
import os
import shutil
import tempfile
import glob
class PlaylistDownloader:
targetDir = ''
totalVideos = 0
downloaded = 0
def setTarget(self, target):
self.targetDir = os.path.realpath(target) + '/';
return self.targetDir;
def download(self, playlistId):
print 'Getting playlist information ... '
data = self.fetchInfo(playlistId)
self.totalVideos = int(data['feed']['openSearch$totalResults']['$t'])
print 'Total videos to download: ' + str(self.totalVideos)
playlistDir = self.createPath(self.targetDir, data['feed']['title']['$t']);
os.chdir(self.setTarget(playlistDir))
self.downloaded = 1;
while(self.downloaded <= self.totalVideos):
data = self.fetchInfo(playlistId, self.downloaded, 50)
self.downloadEntires(data['feed']['entry'])
def downloadEntires(self, entries):
for entry in entries:
group = entry['media$group'];
if self.downloadEntry(group['yt$videoid']['$t'], group['media$title']['$t']):
self.downloaded = self.downloaded + 1
print
def downloadEntry(self, ytId, ytTitle):
print ytId + '(' + str(self.downloaded).zfill(3) + '):', ytTitle, '...'
existing = glob.glob('*' + ytId + '.*');
filtered = [x for x in existing if not x.endswith('part')]
if filtered.__len__() > 0:
print 'alreary exists, skipping...'
return True
try:
os.system('youtube-dl -t --audio-format=best http://www.youtube.com/watch?v=' + ytId)
return True
except KeyboardInterrupt:
sys.exit(1)
except Exception as e:
print 'failed: ', e.strerror
return False
def fetchInfo(self, playlistId, start = 1, limit = 0):
connection = httplib.HTTPConnection('gdata.youtube.com')
connection.request('GET', '/feeds/api/playlists/' + str(playlistId) + '/?' + urllib.urlencode({
'alt' : 'json',
'max-results' : limit,
'start-index' : start,
'v' : 2
}))
response = connection.getresponse()
if response.status != 200:
print 'Error: Not a valid/public playlist.'
sys.exit(1)
data = response.read()
data = json.loads(data)
return data
def createPath(self, path, title):
title = title.replace('/', '')
number = ''
if os.path.exists(path + title) == True and os.path.isdir(path + title) == False:
while(os.path.exists(path + title + str(number)) == True and os.path.isdir(path + title + str(number)) == False):
if number == '':
number = 0
number = number + 1
if os.path.exists(path + title + str(number)) == False:
os.mkdir(path + title + str(number))
return path + title + str(number)
if __name__ == '__main__':
if len(sys.argv) < 2:
print 'Usage: youtube-dl-playlist PLAYLIST_ID [DESTINATION_PATH]'
sys.exit(1)
else:
if sys.argv[1][0] == 'P' and sys.argv[1][1] == 'L':
PLAYLIST_ID = sys.argv[1][2:]
else:
PLAYLIST_ID = sys.argv[1]
downloader = PlaylistDownloader()
if len(sys.argv) == 3:
downloader.setTarget(sys.argv[2] + '/')
else:
downloader.setTarget('./')
downloader.download(PLAYLIST_ID);