From 6793efb32950e3741a17277355fe84094c1b8a32 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Thu, 17 Oct 2019 14:23:13 +0200 Subject: [PATCH] python script that also downloads the videos via youtube-dl --- Pipfile | 13 ++++++ Pipfile.lock | 101 ++++++++++++++++++++++++++++++++++++++++ SaveMyPlaylist.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 SaveMyPlaylist.py diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..f054529 --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + +[requires] +python_version = "3.7" + +[packages] +google-api-python-client = "==1.7.11" +youtube_dl = "==2019.10.16" + +[dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..e1a7e2a --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,101 @@ +{ + "_meta": { + "hash": { + "sha256": "0b25aa17f2c8f2ecd8768ad8eb85313cdf7682655c8179c7fb62068bf0e4ed9d" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "cachetools": { + "hashes": [ + "sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae", + "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a" + ], + "version": "==3.1.1" + }, + "google-api-python-client": { + "hashes": [ + "sha256:3121d55d106ef1a2756e8074239512055bd99eb44da417b3dd680f9a1385adec", + "sha256:a8a88174f66d92aed7ebbd73744c2c319b4b1ce828e565f9ec721352d2e2fb8c" + ], + "index": "pypi", + "version": "==1.7.11" + }, + "google-auth": { + "hashes": [ + "sha256:0f7c6a64927d34c1a474da92cfc59e552a5d3b940d3266606c6a28b72888b9e4", + "sha256:20705f6803fd2c4d1cc2dcb0df09d4dfcb9a7d51fd59e94a3a28231fd93119ed" + ], + "version": "==1.6.3" + }, + "google-auth-httplib2": { + "hashes": [ + "sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445", + "sha256:f1c437842155680cf9918df9bc51c1182fda41feef88c34004bd1978c8157e08" + ], + "version": "==0.0.3" + }, + "httplib2": { + "hashes": [ + "sha256:34537dcdd5e0f2386d29e0e2c6d4a1703a3b982d34c198a5102e6e5d6194b107", + "sha256:409fa5509298f739b34d5a652df762cb0042507dc93f6633e306b11289d6249d" + ], + "version": "==0.14.0" + }, + "pyasn1": { + "hashes": [ + "sha256:62cdade8b5530f0b185e09855dd422bc05c0bbff6b72ff61381c09dac7befd8c", + "sha256:a9495356ca1d66ed197a0f72b41eb1823cf7ea8b5bd07191673e8147aecf8604" + ], + "version": "==0.4.7" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:0c35a52e00b672f832e5846826f1fb7507907f7d52fba6faa9e3c4cbe874fe4b", + "sha256:b6ada4f840fe51abf5a6bd545b45bf537bea62221fa0dde2e8a553ed9f06a4e3" + ], + "version": "==0.2.7" + }, + "rsa": { + "hashes": [ + "sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66", + "sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487" + ], + "version": "==4.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "uritemplate": { + "hashes": [ + "sha256:01c69f4fe8ed503b2951bef85d996a9d22434d2431584b5b107b2981ff416fbd", + "sha256:1b9c467a940ce9fb9f50df819e8ddd14696f89b9a8cc87ac77952ba416e0a8fd", + "sha256:c02643cebe23fc8adb5e6becffe201185bf06c40bda5c0b4028a93f1527d011d" + ], + "version": "==3.0.0" + }, + "youtube-dl": { + "hashes": [ + "sha256:2d93776170dad5ef7b2d2cafdd0bdfb3db625e71d55ab66d725e04d05ce64d75", + "sha256:7c78705c4b43f032df751d7791821bea80a80bc26a024514e194e2b7cdd3a643" + ], + "index": "pypi", + "version": "==2019.10.16" + } + }, + "develop": {} +} diff --git a/SaveMyPlaylist.py b/SaveMyPlaylist.py new file mode 100644 index 0000000..871c7c8 --- /dev/null +++ b/SaveMyPlaylist.py @@ -0,0 +1,115 @@ +from __future__ import unicode_literals + +import os + +import googleapiclient.discovery +import googleapiclient.errors +import youtube_dl + + +class MyLogger(object): + def debug(self, msg): + pass + + def warning(self, msg): + pass + + def error(self, msg): + print(msg) + + +def my_hook(d): + if d['status'] == 'finished': + print('Download finished!') + + +class SaveMyPlaylist: + SCOPES = ['https://www.googleapis.com/auth/youtube.readonly'] + API_NAME = 'youtube' + API_VERSION = 'v3' + + CHANNEL = 0 + TITLE = 1 + VIDEO_ID = 2 + + + ILLEGAL_CHARS = ['NUL', '\',''//', ':', '*', '"', '<', '>', '|'] + + def __init__(self, apiKey, playlistId): + self.__apiKey = apiKey + self.__playlistId = playlistId + self.__items = self.__fetch_playlist_items() + + def __fetch_playlist_items(self): + youtube = googleapiclient.discovery.build(self.API_NAME, self.API_VERSION, developerKey=self.__apiKey) + request = youtube.playlistItems().list( + part='snippet', + playlistId=self.__playlistId, + maxResults=50, + ) + + response = request.execute() + + items = [] + + for item in response['items']: + snippet = item['snippet'] + title = snippet['title'] + channel = snippet['channelTitle'] + videoId = snippet['resourceId']['videoId'] + items.append((channel, title, videoId)) + print('{} - {} ({})'.format(channel, title, videoId)) + + print('\n>>> Found {} items\n'.format(len(items))) + return items + + def download_items(self, destinationFolder, debug=False): + print('>>> Scanning destination folder...') + downloadedVideos = [f for f in os.listdir(destinationFolder) if + os.path.isfile(os.path.join(destinationFolder, f))] + + print('>>> Found {} already downloaded videos'.format(len(downloadedVideos))) + + print('\n>>> Started Downloading...') + newVideos = [] + for idx, item in enumerate(self.__items): + fileName = '{} - {}.mp4'.format(item[self.TITLE], item[self.CHANNEL]) + fileName = self.__escape_file_name(fileName) + if fileName in downloadedVideos: + print('Skipping {}/{}: "{}" as it already exists'.format(idx + 1, len(self.__items), fileName)) + continue + + print('Downloading {}/{}: "{}"'.format(idx + 1, len(self.__items), fileName)) + newVideos.append(item) + + ydl_opts = { + 'format': 'bestaudio/best', + 'merge_output_format': 'mp4', + 'outtmpl': os.path.join(destinationFolder, fileName), + 'logger': MyLogger(), + 'progress_hooks': [my_hook], + } + + if debug: + continue + + with youtube_dl.YoutubeDL(ydl_opts) as ydl: + ydl.download(['https://www.youtube.com/watch?v={}'.format(item[self.VIDEO_ID])]) + + print('\n>>> Finished Downloading') + print('Downloaded {} new videos'.format(len(newVideos))) + + def __escape_file_name(self, fileName): + for char in self.ILLEGAL_CHARS: + fileName = fileName.replace(char, '') + + return fileName + + +if __name__ == '__main__': + API_KEY = 'AIzaSyD1cQOPzYDRe5pylXEFsQw6u-MaBSOX09Y' + PLAYLIST_ID = 'PL7F-5FkCMt0F86pdKUaiTStIloZYDVfzl' + DESTINATION_FOLDER = 'C:/Users/ROGO2/Desktop/123' + + saveMyPlaylist = SaveMyPlaylist(API_KEY, PLAYLIST_ID) + saveMyPlaylist.download_items(DESTINATION_FOLDER, True) -- GitLab