YouTubeDownloader

追記:もうちょいしっかりしたやつ

g:spearmint:id:omochist:20061008:p1

本題

せっかくsimple-rssもある程度使えるようになってきたし,応用編です.ついでに,巷で流行のscrAPIを使ってみようという目論見もあり.久しぶりにガッツリと書いた気分です.

やりたいこと

YouTubeが,タグごとにRSSを配信しているのは,あなたがたもよくご存知のはず…(CV:河原木志穂).
そこで,そのRSSにある動画を,全部ローカルに保存しちゃおうと言うのがこの企画.

特徴

gemを2つ使っています.

  • simple-rss
  • scrapi

ソースを俺も走らせたい!って人は,あらかじめ,この2つをインストールしておいてください.
また,大きなお世話ですが,ビデオ単体でも落とせるように,ビデオのURLからビデオを落とす処理だけを関数にしておきました.

注意点

スクリプト自体のインタフェースは,極めて貧相です.理想は標準入力でタグを入力して,って感じですが,「そこは拘らなくて良いだろう」と思ったので作ってません.
また,curlを使っているので,curlが無い人はその部分をwgetなり何なりに書き換えてください.始めはrioでやってたんですが,エラーが発生したので断念.

使い方

urlを適当に書き換えて走らせてください.エラーのキャッチとか一切考慮してませんので,ビクビクしながらお願いします.

お願い

無いかもしれませんが,もし「このソースを元に,こんな風に改良してみたよ!」とか「ここはこーすれば良い!」などなどあれば,トラバなりコメントなりくれると,嬉しいです.


それでは,多少長くなるので続きにソースコードを貼付けます.

ソースコード

require 'net/http'
require 'uri'
require 'rubygems'
require 'simple-rss'
require 'scrapi'

def get_video(link)
  return if link !~ /www.youtube.com/
  uri = URI.parse(link)
  uri.path = '/watch'
  
  body = Net::HTTP.get_response(uri).body
  
  script = Scraper.define {
    process "div#interactDiv >script", :script => :text
    result :script
  }.scrape(body)
  
  title = Scraper.define {
    process "title", :title => :text
    result :title
  }.scrape(body, :parser => :html_parser).gsub(/\s/u, '').sub(/YouTube-/,'')
  
  query = script[/video_id=([^&]+)&l=(\d)+&t=([^\"]+)/].gsub(/&l=\d+/, '')

  uri.path, uri.query = '/get_video', query
  res = Net::HTTP.get_response(uri)
  unless File.exist?("#{title}.flv")
    `curl #{res['location']} > '#{title}.flv'`
  else
    puts "もうそのビデオは持ってる"
  end
end

# feed url
# タグは"musashi mad"です.
url = "http://www.youtube.com/rss/tag/musashi%20mad.rss" 

uri = URI.parse(url)

rss = nil
Net::HTTP.start(uri.host) do |http|
  rss = SimpleRSS.new(http.request_get(uri.path).body)
end

links = Array.new
rss.items.each do |item|
  links << item.link
end


threads = Array.new
links.each do |link|
  threads << Thread.start(link) do |l|
    get_video(l)
  end
end

threads.each do |t| t.join end
puts "complete"