pytubeでYouTubeの動画ダウンローダーを作る
目次
Windowsでpytubeを動かすまで
pytubeというpythonのライブラリを見つけました。
https://github.com/nficano/pytube
簡単にYouTubeの動画をダウンロードできると書いてあって、ちょっと面白そうなので試してみた記録です。
Windowsにpythonを入れる
Windowsでやりたいので、まずはWindowsにpythonを入れるところからのスタート。pythonもせっかくなので3を入れてみようと思います。
こちらからWindows用のpythonインストーラをダウンロード。
https://www.python.org/downloads/windows/
64bit環境なので、Python 3.6.4 - Windows x86-64 executable installer とかでいいんじゃないでしょうか。
pathを通すにチェックを入れてInstall Nowをクリックするとインストール開始。
pipもインストールされるようです。
インストールが終わったら、コマンドプロンプトを立ち上げて「python」と打ってみて、pythonが立ち上がればOK。
いったん、Ctrl+Z > Enterでpythonを抜けます。
pytubeを入れる
すでにpipが使えるはずなので、Windowsのコマンドプロンプトを立ち上げて、
pip install pytube
これだけ。
こんな画面が出てあっけなくインストール完了。
バージョンは8.0.2のようです。
pytubeの実行
Eドライブ直下に「py」というフォルダを作り、ここを作業フォルダにしようと思います。
説明書のサンプルでは対話式で進めていますが、せっかくなのでテキストエディタとかIDLEでスクリプトを書きます。
from pytube import YouTube YouTube('http://youtube.com/watch?v=9bZkp7q19f0').streams.first().download()
こんな感じでサンプル通りに書いたものを作業フォルダ「py」の中に、test.pyとして保存します。
コマンドでEドライブのpyに移動して、python test.py というふうに実行します。
しばし沈黙の後、プロンプトが戻ります。
おや、何もおきないかな? と思いましたが、
pyフォルダの中に動画ファイルができていました。
無事成功です。
ほんと簡単ですね。
もう少しつっこんだpytubeの使い方
せっかくなので、もう少し詳しいpytubeの使い方を見ていきます。
※適当なので、正確な解説はこちらのドキュメントをどうぞ!
https://python-pytube.readthedocs.io/en/latest/
YouTubeオブジェクト
from pytube import YouTube yt = YouTube('https://www.youtube.com/watch?v=ssuiqtreiBg')
このように、YouTube()クラスに動画のURLを渡すとYouTubeオブジェクト(ここではyt)ができます。yt.title で動画のタイトル、yt.thumbnail_url で動画のサムネイルのURLが取得できたりします。
実例
from pytube import YouTube yt = YouTube('https://www.youtube.com/watch?v=ssuiqtreiBg') print(yt.title) print(yt.thumbnail_url)
実行すると、このような結果になります。
StreamQueryオブジェクト
yt.streams はStreamQueryというオブジェクトになります。これは、その動画に対してどのようなフォーマット形式の動画や音声が用意されているのかの一覧情報です。説明よりも中身を見てみるほうがわかりやすいと思うので、まずは・・・
all()でStreamQueryの中身を全部見る
all()でStreamQueryの中身を全部見ることができます。データはリストなのでforで出力してみます。
from pytube import YouTube yt = YouTube('https://www.youtube.com/watch?v=ssuiqtreiBg') s = yt.streams.all() for i in s: print (i)
ズラっと出てきましたが、この動画にこれだけフォーマットの用意があるよーということです。中には動画だけ音声だけのものもありますが、これは、Dynamic Adaptive Streaming over HTTP (DASH)という技術をサポートするためのものだそうです。詳しくないのでアレですが、環境などによってこれらの動画×音声の組み合わせを切り替えて再生できるそうです。
なるほど。
一方、動画と音声が一つになっている旧来の方式(progressive download)も用意されています。ただしこれは720p以下のものしかないそうです。
filterを使う
このリストに対して、いろいろな条件のフィルタをかけることでデータの絞り込みをすることができます。
progressiveを全部
yt.streams.filter(progressive=True).all()
DASH(adaptive)を全部
yt.streams.filter(adaptive=True).all()
mime_typeがvideo/mp4を全部
yt.streams.filter(mime_type='video/mp4').all()
(mime_typeの)typeがvideoを全部
yt.streams.filter(type='video').all()
(mime_typeの)subtypeがmp4を全部
yt.streams.filter(subtype='mp4').all()
filterの重ねがけ
subtypeがmp4+progressiveを全部
yt.streams.filter(subtype='mp4', progressive=True).all()
この書式でも可です
yt.streams.filter(subtype='mp4').filter(progressive=True).all()
リストを並び替える
order_by()を使うことでリストの並び替えができます。order_by()に並び順に使用する属性を渡し、asc() またはdesc()で昇順/降順を指定します。
progressiveを解像度の高い順に全て並べる
yt.streams.filter(progressive=True).order_by('resolution').desc().all()
※注意
Note that order_by cannot be used if your attribute is undefined in any of the Stream instances, so be sure to apply a filter to remove those before calling it.
リストに、order_byに使う属性を持たないデータが混じってちゃダメ。
例えば、解像度を持たない音声のみのストリームが入っているリストに対しては、解像度での order_byはできないということです。
具体的には、mp4で一番解像度の高いストリームを取得しようと思い、下記のようにしたとします。
yt.streams.filter(subtype='mp4').order_by('resolution').desc().first()
するとこんなエラーが出ます。
TypeError: '<' not supported between instances of 'NoneType' and 'str'
subtype='mp4'というフィルタリングだと、音声のみのストリームがリストに入ってきます。すると、このリストに対しては解像度でorder_byができないというわけです。
これを回避するには、
対象をvideo/mp4にするとか、
yt.streams.filter(mime_type='video/mp4').order_by('resolution').desc().first()
progressiveにしてみるとか
yt.streams.filter(progressive=True).order_by('resolution').desc().all()
うまいことorder_byができるようにフィルタしないといけません。
リストの先頭/最後を指定して取ってくる
first()
last()
リストの一番先頭・最後のStreamを取ります。解像度の高い順に並べて、first()を取れば一番解像度の高いデータを指定できます。
itagで指定して取ってくる
get_by_itag(itag)
リストの中からピンポイントでデータを指定したい時に、itagの番号でデータを拾うことができます。
簡単な対話式ダウンローダー
飽きてきたちょっと長くなったので、
対話式のダウンローダーをまとめのサンプルとして置いて、いったんしめます。
from pytube import YouTube url = input("Enter YouTube Video URL : ") yt = YouTube(url) def done(stream, file_handle): print("Done") list = yt.streams.filter(progressive = True).all() for i, j in enumerate(list): print('[{0}]:{1}'.format(i, j)) target = int(input("Enter Stream# : ")) yt.register_on_complete_callback(done) list[target].download()
実行すると、動画のURLを入れろと言われます。
入れるURLはhttps://www.youtube.com/watch?v=hogehoge のような形式です。後ろに他のパラメーターがゴチャゴチャとくっついていても大丈夫みたいです。URLを入れてEnterを押して少しすると、フォーマット一覧が出てきて、欲しい番号を入れろと言われます。
先頭の[0]とか[1]の番号を入れます。ここでは0番がよさそうなので、0と入力。ダウンロードが終わるとDoneと出て終了です。
以上
※フィルタをかけているので、このサンプルではprogressive形式だけがリストアップされます。他の形式も見たい場合はフィルタの部分をいじってください。
次はDASH形式の高画質動画と高音質音声の合体に挑戦!
いつになるかは未定w
mp3への変換あたりからにしようかしら・・・
2018/2/8 追記
pytubeがエラーを吐いて使えなくなりました。
pytubeが9.0.4にバージョンアップしているようなので、バージョンアップしてみたのですが、またエラー。
あれ? でもエラーが変わりました。
from pytube.contrib.playlist import Playlist ModuleNotFoundError: No module named 'pytube.contrib'
モジュールの読み込みができていないようです。
pytubeのインストールされている場所を見てみると・・・
なんと、contribフォルダがありませんw
pip経由でインストールすると、このフォルダが入らないようです。
作者が入れ忘れたのかな?
ここからcontribとその中身を手動で入れたら動きました。やれやれ。
https://github.com/nficano/pytube
Windowsのpytubeはこのあたりに入っています。
C:\Users\********\AppData\Local\Programs\Python\Python36\Lib\site-packages\pytube
さらに追記
上記の問題はfixされたようです