kusoimox.hatenablog.jp
以前うpした記事で,pytube
でYouTubeの動画がダウンロードできる~とい言ったんですが,最近久しぶりに使うと,
itagは取れるんだけど,動画のダウンロードでエラーが出て,使えなくなちゃった...
そこで,調べると,
っとあったんですが,原因が少し違うような...よう分りまへんわ~
っということで,それならスクリプト自作してしまえってことになり,以下のようになりました.
スクリプト構成の土台はpytube
ですけどね.
# -*- coding: utf-8 -*- # 動画 movie = [5,6,17,18,22,34,35,37,38,43,44,45,46,59,78,82,83,84,85,91,92,93,94, 95,96,100,101,102,132,151] # 動画像のみ video = [13,36,133,134,135,136,137,138,160,167,168,169,170,212,218,219,242, 243,244,245,246,247,248,264,266,271,272,278,298,299,302,303,308,313, 315,330,331,332,333,334,335,336,337] # 音声のみ audio =[139,140,141,171,172,249,250,251] from urllib.parse import unquote from time import sleep import re,sys,requests,ast,wx,os class youtube: def save(self): app=wx.App() # アプリケーションのオプジェクトを生成 wx.MessageBox('保存先フォルダを選択してください','フォルダ選択',wx.STAY_ON_TOP) dialog = wx.DirDialog(None, message='ファイルを選択してください',style=wx.DD_CHANGE_DIR | wx.OK | wx.STAY_ON_TOP) # ファイルが選択されたとき if dialog.ShowModal() == wx.ID_OK: # 選択したファイルパスを取得する self.path = dialog.GetPath() dialog.Destroy() def download(self,itag_no): itag_no = int(itag_no) for i in self.itag: if i['itag'] == itag_no: dl_url = i['url'] break title = re.sub(r'[\\/:*?"<>|]+','',self.videoDetails['title'].replace(' ','')) if (itag_no in movie) or (itag_no in video): kakuchoshi = '.mp4' elif itag_no in audio: kakuchoshi = '.wmv' title = title + kakuchoshi path = os.path.join(self.path,title) sys.stderr.write('downloading...\n') data = requests.get(dl_url).content with open(title,mode='wb') as f: f.write(data) sys.stderr.write('download finish!\n') def video_info_url(self,url): video_id = re.search(r'(?:v=|\/)([0-9A-Za-z_-]{11}).*', url).groups(1)[0] if video_id == None: return False watch_url = 'https://youtube.com/watch?v=' + video_id watch_html = requests.get(watch_url).content.decode() eurl = 'https://youtube.googleapis.com/v/{}'.format(video_id) embed_html = 'https://www.youtube.com/embed/{}'.format(video_id) params = { 'video_id':video_id, 'el':'detailpage', 'ps':'default', 'hl':'en_US' } rurl = requests.get('https://youtube.com/get_video_info',params=params).url res = unquote(requests.get(rurl+'?eurl={}'.format(eurl)).text) self.itag=[] info = re.search(r'player_response=({.+})&',res) if info != None: info = info.groups(1)[0] info = info.strip() info = info.replace('"',"'") info = info.replace('true','True') info = info.replace('false','False') info = info.replace('null','None') try: video_info = ast.literal_eval(info) except SyntaxError: return False del info else: return False streamingData = video_info['streamingData'] self.itag += streamingData['formats'] self.itag += streamingData['adaptiveFormats'] self.playbackTracking = video_info['playbackTracking'] self.videoDetails = video_info['videoDetails'] return True def __init__(self,url): self.save() sys.stderr.write('info getting...\n') while True: try: res = self.video_info_url(url) except requests.exceptions.SSLError: continue except requests.exceptions.ConnectionError: continue if res: break sleep(60) for i in self.itag: if i['itag'] in movie: sys.stderr.write('動画 ') elif i['itag'] in video: sys.stderr.write('動画像のみ ') elif i['itag'] in audio: sys.stderr.write('音声のみ ') else: sys.stderr.write('None ') sys.stderr.write('itag {0}:[type:{1} bitrate:{2} quality:{3}]\n'.format( i['itag'],i['mimeType'].split('=')[-1],i['bitrate'],i['quality'] )) if __name__ == '__main__': url = input('url:') yt = youtube(url) yt.download(input('choice itag number:'))
”https://www.youtube.com/watch?v=動画ID&feature=youtu.be”みたいなURLが対象です.基本はこの形のURLで. え~と,”https://youtu.be/動画ID”でもイケましたね.共有からURLをコピーしたときはこの形ですからね. 通常はitagを22,なければ18を選択すれば,動画がダウンロードできます.
参考
- PythonでURLエンコード/デコード - Bye Bye Moore
- PythonのURLとクエリパラメータのパースまとめ - Qiita
- PythonでURLエンコード・デコード(urllib.parse.quote, unquote) | note.nkmk.me
- python3 文字列を辞書に変換 - Qiita
- [Python] ast.literal_evalを使って文字列を評価する | aoshiman.org
- 辞書型 - python 辞書 追加 - 入門サンプル
- ファイル名として無効な文字を削除(Python) - Qiita
- Python 3.x - python3 辞書型をテキストに書き出し|teratail
- PythonにおいてのJSONファイルの取扱いあれこれ - Qiita
- pythonエラーまとめ - Qiita
- Python - 'module' object is not callableの意味がわかりません。|teratail
+pytube
とPython参考書
2020/8/30追記:ダウンロードできません
'https://youtube.com/get_video_info'へのアクセスができません... ブラウザで人手で行えばアクセスしてデータを得られるのですが, スクリプトから自動的にアクセスしようとすると”HTTP Status Code:429”が出ます. 以上のリンクへのアクセスだけでなく,ログインもスクリプトからはできない模様.
アクセスのし過ぎというより,YouTube自体がスクリプトによる自動アクセスを拒絶しているような気がします. どうしてもやりたい場合はサービスに登録してGoogleのAPIを使うしかないと思われます.
色々スクリプト書き直したんですが,”HTTP Status Code:429”でアクセスできなくなりお手上げです...