YouTubeのfmt22をタイトルつきで保存したかったので手抜きPythonスクリプトを書いてみた。
$ python yt.py -d ./ 'http://..../watch?=....' 'http://..../watch?=....'
とか
$ python yt.py -d ./
(標準入力に1行1URLでURLのリストを渡す)
のようにして使う。
-dで指定したディレクトリ(省略時はカレントディレクトリ)に”元のタイトル (YouTube HD).mp4″というファイル名で保存。
昔書いたダウンローダを直しても良かったのだが、ソースを見るのも面倒だったので書き下ろし。汚い。
あとJavaScriptの辞書をPythonの辞書にするのにevalを使うという恐ろしいことをしている。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys, re, urllib2, getopt
def dodownload(url, path):
"""download [url] to [path]"""
v = urllib2.urlopen(url)
fo = file(path, 'wb')
buf = []
while True:
buf = v.read(1024*1024)
if len(buf)==0:
break
fo.write(buf)
sys.stdout.write(u'.')
sys.stdout.flush()
print
fo.close()
v.close()
return True
def clean_title(title):
title = re.sub(ur':|\||\\|/', '', title)
title = re.sub(ur'&', '&', title)
return title
def download(url, dir):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5'
}
# get html
req = urllib2.Request(url, None, headers)
res = urllib2.urlopen(req)
html = res.read()
res.close()
# get title
title_mo = re.compile(ur'<meta name="title" content="(.*?)">').search(html)
title = title_mo.group(1)
title = clean_title(title)
# get swfArgs
swfArgs_mo = re.compile(ur'var swfArgs = ({.*?});', re.S).search(html)
swfArgs_js = swfArgs_mo.group(1).replace('null', 'None')
swfArgs = eval(swfArgs_js)
# get Video
video_url = 'http://jp.youtube.com/get_video?video_id=%(video_id)s&t=%(t)s&el=detailpage&ps=&fmt=22' % swfArgs
print title, video_url
# download video
dlpath = os.path.join(dir, title+'(YouTube HD).mp4')
if not os.access(dlpath, os.F_OK):
return dodownload(video_url, dlpath)
return False
options, rest = getopt.getopt(sys.argv[1:], 'd:h')
opt_dict = {
'dir': './'
}
for o, v in options:
if o=='-d':
opt_dict['dir'] = v
if o=='-h':
print 'usage: echo URLS | python yt.py -d SAVE_DIR'
sys.exit(0)
url_list = rest
if len(url_list)==0:
url_list = sys.stdin.readlines()
for u in url_list:
try:
if download(u, opt_dict['dir']):
continue
except Exception, e:
print e
print 'failed'
