我有一个python应用程序,我有一个包含多个网址的变量。
此刻我使用的是这样的东西:
WSASend
但是这样我只下载了一个又一个视频。我如何下载,让我们同时说3个视频? (不是来自youtube所以没有播放列表或频道)
我不需要python中的多线程,但多次调用youtube-dl,拆分数组。所以从python的角度来看可以在线程上。
答案 0 :(得分:2)
使用Pool
:
import multiprocessing.dummy
import subprocess
arr = [
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc'},
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'http://vimeo.com/56015672'},
{'vpath': '%(playlist_title)s/%(title)s-%(id)s.%(ext)s',
'url': 'https://www.youtube.com/playlist?list=PLLe-WjSmNEm-UnVV8e4qI9xQyI0906hNp'},
]
email = 'my-email@example.com'
password = '123456'
def download(v):
subprocess.check_call([
'echo', 'youtube-dl',
'-u', email, '-p', password,
'-o', v['vpath'], '--', v['url']])
p = multiprocessing.dummy.Pool(concurrent)
p.map(download, arr)
multiprocessing.dummy.Pool
是Pool
的基于线程的轻量级版本,在这里更合适,因为工作任务只是启动子进程。
请注意,而不是os.system
,subprocess.check_call
,这会阻止您之前代码中的command injection vulnerability。
另请注意,youtube-dl output templates非常强大。在大多数情况下,您实际上并不需要自己定义和管理文件名。
答案 1 :(得分:1)
我使用threading
库实现了同样的目的,该库考虑了一种生成新进程的简便方法。
import os
import threading
import youtube_dl
COOKIE_JAR = "path_to_my_cookie_jar"
def download_task(videos, output_dir):
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
if not os.path.isfile(COOKIE_JAR):
raise FileNotFoundError("Cookie Jar not found\n")
ydl_opts = {
'cookiefile': COOKIE_JAR,
'outtmpl': f'{output_dir}/%(title)s.%(ext)s'
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(videos)
if __name__ == "__main__":
output_dir = "./root_dir"
threads = []
for playlist in many_playlists:
output_dir = f"{output_dir}/playlist.name"
thread = threading.Thread(target=download_task, args=(playlist, output_dir)
threads.append(thread)
# Actually start downloading
for thread in threads:
thread.start()
# Wait for all the downloads to complete
for thread in threads:
thread.join()