ニコニコ動画ダウンローダ
以前、Irvine(via OLE) でダウンロードする Perl スクリプトを書いたけど、なんか FLV のダウンロードにも Cookie が必要になっているっぽいので、Firefox の Cookie を使ったり、ファイル名をタイトルから取得したり Progress Bar を出したりとかするのをこの間 Python でリライトした。progressbar.py は http://cheeseshop.python.org/pypi/progressbar から。
一応、ファイル名はタイトルから取得するけど、「/」が含まれていていたり、CP932 に含まれない文字を使っていたりすると失敗する*1。
で、Cookie は -c オプションで Firefox のプロファイルディレクトリ以下の cookie.txt を指定しませう。というか、ニコニコ動画はログインすると以前ログインした Cookie が無効になるので、こうしないとやってられない。
#!/usr/bin/env python import sys, urllib2, cookielib, re, cgi DEFAULT_COOKIE_FILE = 'cookies.txt' FILESYSTEM_ENCODING = 'cp932' def get_nicovideo_id(url): pat = re.compile('http://www.nicovideo.jp/watch/(.*)') m = pat.match(url) if m: return m.group(1) else: return None def get_title(url, opener): content = get(url, opener).decode('utf-8') pat = re.compile(r'<h1><a [^>]*>(.*)</a></h1>', re.M) m = pat.search(content) if m: return m.group(1) else: raise KeyError('Not Found') def get_flv_url(nid, opener): get_flv_url = 'http://www.nicovideo.jp/api/getflv?v=%s' % urllib2.quote(nid) return cgi.parse_qs(get(get_flv_url, opener))['url'][0] def get(url, opener): fp = opener.open(url) try: content = fp.read() return content finally: fp.close() def retrieve(url, filename, opener): from progressbar import ProgressBar, Percentage, Bar, ETA, FileTransferSpeed reader = opener.open(url) writer = file(filename, 'w') total = int(reader.headers.get('content-length')) print filename widgets = [ Percentage(), ' ', Bar(marker = '#', left = '[', right = ']'), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets = widgets, maxval = total) l = 0 while True: block = reader.read(512) if not block: break writer.write(block) l += len(block) pbar.update(l) pbar.finish() reader.close() writer.close() def main(cookie_file, args): cj = cookielib.MozillaCookieJar() cj.load(cookie_file) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) for url in args: nid = get_nicovideo_id(url) flv_url = get_flv_url(nid, opener) title = get_title(url, opener) filename = title.encode(FILESYSTEM_ENCODING) + '.flv' retrieve(flv_url, filename, opener) if __name__ == '__main__': import optparse parser = optparse.OptionParser() parser.add_option('-c', '--cookie', dest = 'cookie') (opts, args) = parser.parse_args() if opts.cookie is not None: cookie_file = opts.cookie else: cookie_file = DEFAULT_COOKIE_FILE main(cookie_file, args)