wgetでYouTube等から動画を落とす
Rubyに戻ってみました。selfを書かなくて済むのはいいんですが、Pythonに慣れてきたせいか、endを書くのが少し面倒になってます。後、インスタンスごとにメソッドの振る舞いを変えられるのはいいです。新しくクラスを作らなくて済みますし。
#!ruby require 'net/http' require 'cgi' require 'kconv' save_dir = 'c:/My Documents' interval = 3 module Video class Error < StandardError; end class InvalidUrlError < Error; end VideoDetail = Struct.new(:id, :dl_url, :title, :ext, :encoding) def get_detail(url) @@videos.each do |video| begin return video.get_detail(url) rescue InvalidUrlError raise if video === @@videos.last end end end module_function :get_detail class Video def initialize(url_re, dl_url_re, title_re=nil, api_url=nil, ext=".flv", encoding=Kconv::UTF8) @url_re = url_re @dl_url_re = dl_url_re @title_re = title_re @api_url = api_url @ext = ext @encoding = encoding end def get_detail(url) id = extract_video_id(url) if @api_url video_url = @api_url % id else video_url = url end content = get_content(video_url) params = extract_dl_url_params(content) dl_url = build_dl_url(params) title = extract_title(content) VideoDetail.new(id, dl_url, title, @ext, @encoding) end private def extract_video_id(url) @url_re.match(url).to_a[1] or raise InvalidUrlError.new('invalid video url') end def get_content(url) begin res = Net::HTTP.get_response(URI.parse(url)) raise unless Net::HTTPSuccess === res res.body rescue raise Error.new('unable to download video page') end end def extract_dl_url_params(content) @dl_url_re.match(content).to_a[1..-1] or raise Error.new('unable to extract download url params') end def build_dl_url(params) params.first end def extract_title(content) @title_re.match(content).to_a[1] if @title_re end end @@videos = [] youtube = Video.new( %r!\Ahttp://(?:\w+\.)youtube\.com/watch\?v=([\w-]+)!, %r!watch_fullscreen\?.*?video_id=([\w-]+).*?&t=([\w-]+)!, %r!<title>YouTube - ([^<>]*)</title>! ) def youtube.build_dl_url(params) "http://www.youtube.com/get_video?video_id=%s&t=%s" % params end @@videos << youtube veoh = Video.new( %r!\Ahttp://www\.veoh\.com/videos/(\w+)!, %r!fullPreviewHashPath="([^"]+)"!, %r!title="([^"]*)"\s+dateAdded=!, 'http://www.veoh.com/rest/video/%s/details' ) @@videos << veoh dailymotion = Video.new( %r!http://www.dailymotion\.com/.*?/video/([\w/-]+)!, %r!(http%3A%2F%2Fwww\.dailymotion\.com%2Fget%2F\d{2}%2F320x240%2Fflv%2F\d+\.flv%3Fkey%3D\w+)!, %r!<h1 class="nav with_uptitle">([^<>]*)</h1>! ) def dailymotion.build_dl_url(params) CGI.unescape(params.first) end @@videos << dailymotion amebavision = Video.new( %r!http://vision\.ameba\.jp/watch\.do.*?\?movie=(\d+)!, %r!<imageUrlLarge>([^<>]+)</imageUrlLarge>!, %r!<item>\s*<title>([^<>]*)</title>!, "http://vision.ameba.jp/api/get/detailMovie.do?movie=%s" ) def amebavision.build_dl_url(params) flv_url = params.first flv_url['//vi'] = '//vm' flv_url['/jpg/'] = '/flv/' flv_url['_4.jpg'] = '.flv' flv_url end @@videos << amebavision yourfilehost = Video.new( %r!http://(?:www\.)?yourfilehost\.com/media\.php\?cat=video&file=([\w.-]+)\.!, %r!videoembed_id=([\w%.-]+)&! ) def yourfilehost.build_dl_url(params) CGI.unescape(params.first) end @@videos << yourfilehost end ARGV.each do |url| begin video = Video.get_detail(url) rescue => e puts "Error: #{e} (#{url})" next end if video.title filename = video.title.kconv(Kconv::SJIS, video.encoding) else filename = video.id end filepath = File.join(save_dir, filename << video.ext) system('wget', '-O', filepath, "--referer=#{url}", video.dl_url) sleep interval end