Amazing-Python-Scripts

Форк
0
198 строк · 6.7 Кб
1
# DownTube is a Youtube Video/Audio downloader script written by XZANATOL
2
# https://www.github.com/XZANATOL
3
# source code can be found on https://github.com/avinashkranjan/Amazing-Python-Scripts
4
from pytube.cli import on_progress
5
from pytube import YouTube, Playlist
6
from optparse import OptionParser
7
import sys
8
import os
9
import re
10

11
# Help menu
12
usage = """
13
<Script> [Options]
14

15
[Options]:
16
  -h, --help        show this help message and exit.
17
  -a, --audio-only  Flag to download only the audio source (True/Flase).
18
  -p, --playlist    Playlist flag if the provided link is a playlist not a single video.
19
  -u, --url         Parameter used to add Youtube link.
20
  -f, --file        Parameter used to add file that contains some Youtube links.
21

22
Notes:
23
1) You can't pass both -f and -u at the same time.
24
2) If a file that exists has the same name of a file to be downloaded, the current file WILL NOT be overwritten.
25
"""
26

27
# load args
28
parser = OptionParser()
29
parser.add_option("-a", "--audio-only", action="store_true", dest="only_audio",
30
                  help="Flag to download only the audio source (True/Flase).")
31
parser.add_option("-p", "--playlist",   action="store_true", dest="playlist",
32
                  help="Playlist flag is the provided link is a playlist not a single video.")
33
parser.add_option("-u", "--url", dest="url",
34
                  help="Parameter used to add Youtube link.")
35
parser.add_option("-f", "--file", dest="file",
36
                  help="Parameter used to add file that contains some Youtube links.")
37

38
pattern = r'res="([0-9]+)p"'  # used for checking available resolutions
39

40

41
def choice_single_link(links):
42
    """Walkthorugh algorithm if -p/--playlist flag is False"""
43
    try:
44
        links = YouTube(links, on_progress_callback=on_progress)
45
    except:
46
        raise "Can't verify link, check internet connectivity/provided link."
47

48
    if only_audio:  # if -a/--audio-only flag is True
49
        count = audio_download([links])  # function accepts a list of urls
50
    else:
51
        count = is_vid([links])  # function accepts a list of urls
52

53
    return count
54

55

56
def choice_playlist(links):
57
    """Walkthorugh algorithm if -p/--playlist flag is True"""
58
    try:
59
        links = Playlist(links)
60
    except:
61
        raise "Can't verify playlist, check internet connectivity/provided link."
62

63
    if only_audio:  # if -a/--audio-only flag is True
64
        count = audio_download(links.videos)
65
    else:
66
        count = is_vid(links.videos)
67

68
    return count
69

70

71
def file_handler(path):
72
    """Reads file that contains Youtube links and downloads them"""
73
    try:
74
        with open(path, "r") as file:
75
            i = 0  # counter for items
76
            for line in file.readlines():
77
                if not "youtube" in line or not line.rstrip("\n"):
78
                    continue
79
                choice_single_link(line.rstrip("\n"))
80
                i += 1
81
        return i
82
    except:
83
        raise "Can't open file, check provided path/read permissions."
84

85

86
def is_vid(lst):
87
    """Filtering function for video downloading"""
88
    # Instead of filtring the video on each approach (playlist or single_vid or file scraping),
89
    # This function takes care of the video filtering for all approaches,
90
    # Just feed her a list of streams and watch the magic. :D
91

92
    # this loop to check the available resolutions for 1 vid (one will apply for all)
93
    resolutions_mp4 = []
94
    resolutions_webm = []
95
    for i in lst:
96
        mp4_res = i.streams.filter(progressive=True, file_extension="mp4")
97
        for res in mp4_res:
98
            resolutions_mp4.append(re.search(pattern, str(res))[1])
99

100
        webm_res = i.streams.filter(progressive=True, file_extension="webm")
101
        for res in webm_res:
102
            resolutions_webm.append(re.search(pattern, str(res))[1])
103
        break
104

105
    print("Select one of the available resolutions:")
106
    print("mp4:", resolutions_mp4)
107
    print("webm:", resolutions_webm)
108
    ext, res = input("[extension] [resolution] > ").split(" ")
109

110
    # check input
111
    if not res in resolutions_mp4+resolutions_webm or not ext in ["mp4", "webm"]:
112
        raise "Invalid Input..."
113

114
    return video_download(lst, ext, res)
115

116

117
def audio_download(objct):  # objct is a list of urls
118
    """Function that downloads provided streams as audios"""
119
    i = 0  # counter for items
120
    for aud in objct:
121
        print("Downloading: " + aud.title)
122
        aud.register_on_progress_callback(on_progress)  # show progress bar
123
        try:
124
            aud.streams.filter(type="audio").order_by(
125
                "abr").desc().first().download()
126
            i += 1
127
        except:
128
            pass
129
        print()  # add a blank line to seperate intersecting progress bars
130

131
    return i
132

133

134
def video_download(objct, ext, res):  # objct is a list of urls
135
    """Function that downloads provided streams as videos"""
136
    i = 0  # counter for items
137
    for vid in objct:
138
        print("Downloading: " + vid.title)
139
        vid.register_on_progress_callback(on_progress)  # show progress bar
140
        try:
141
            stream = vid.streams.filter(
142
                progressive=True, type="video", resolution=res+"p", file_extension=ext).order_by("abr").desc()
143

144
            if len(stream) == 0:  # That if condition is for in case any videos in the playlist doesn't offer the same stream resolution (common in Mix playlists)
145
                print(
146
                    "Couldn't find available resolution for the video, Downloading with the best available one")
147
                stream = vid.streams.filter(progressive=True, type="video", file_extension=ext).order_by(
148
                    "resolution").desc().order_by("abr").desc()
149

150
            stream.first().download()
151
            i += 1
152
        except:
153
            pass
154
        print()  # add a blank line to seperate intersecting progress bars
155

156
    return i
157

158

159
def check_Download_folder():
160
    """Checks if Donwloads folder exists.. If not, then it will create one."""
161
    if os.path.exists("Downloads/"):
162
        os.chdir("Downloads/")
163
    else:
164
        try:
165
            os.mkdir("Downloads")
166
        except:
167
            raise "Couldn't create 'Downloads' folder, Check write permissions"
168
        os.chdir("Downloads/")
169

170

171
# Start checkpoint
172
if __name__ == "__main__":
173
    (options, args) = parser.parse_args()
174

175
    # flags
176
    only_audio = options.only_audio
177
    playlist = options.playlist
178
    link = options.url
179
    file = options.file
180

181
    # validate arguments
182
    if not bool(link) ^ bool(file):  # xor gate
183
        print(usage)
184
        sys.exit()
185

186
    # prepare Downloads directory
187
    check_Download_folder()
188

189
    if link:
190
        if playlist:
191
            count = choice_playlist(link)
192
        else:
193
            count = choice_single_link(link)
194
    else:
195
        count = file_handler(file)
196

197
    # print a small report
198
    print("\n[+]Downloaded {} items".format(count))
199

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.