それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

ニコニコ動画をダウンロードする。Rubyで。

ニコニコ動画を保存してitunesに転送しようかなと。

インストール

パッケージは、sora_hの物を使うことにした。

gem install niconico

ドキュメントには書いてないけど、ruby1.9でしか動かない。1.9が好きになれない僕には、ちょっと不満。

ダウンロードする。

require 'niconico'

nico = Niconico.new('takuya@example.com','*****') #ログインメアド、パスワード
nico.login
$stdout = open("out.flv", "w")
puts nico.video("sm12345456").get_video
$stdout.flush

一覧を取り込む

初音ミクなどのボカロランキングをまとめてダウンロードする。

これはMechanizeでさくっと。

 require 'mechanize'
 nico = Niconico.new('takuya@example.com','*****')
 nico.login
 url = "http://www5.atwiki.jp/hmiku/pages/4386.html"
 m = Mechanize.new
 m.get url
 list = m.page.iframes.map{|e| e.src}.map{|e| e =~ /\/(sm[0-9]+)$/ ; $1}
 list.each{|e|
 video= nico.video(e)
 open("#{e}.flv", "w"){|f| f.write video.get_video }
 }


これで一括ダウンロード。もちろんシングルスレッドで動作させる。マルチスレッドだとダウンロードは出来ない。ニコニコ動画は複数スレッドでつなぐと応答してくれないからね。。。

一応マルチスレッド版もある

#!/usr/bin/env ruby
#--coding: utf-8
require 'niconico' # ruby 1.9限定
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
Thread.abort_on_exception=true


class Niconico
  class Downloader
    require 'thread'
    def initialize(address,pass)
      @address,@pass = address, pass
      @q = Queue.new
      @client = Niconico.new(@address,@pass)
	  @client.agent.max_history=1
      @client.login
    end
    def add_download_list(sm_id)
      @q.push sm_id
    end
    def worker
      t = Thread.new{
          begin 
            sm_id = nil
            retry_cnt = 1
            loop{ 
              sm_id = @q.pop
              video = @client.video sm_id
              open("nicovideo2/#{video.title.gsub(/\//,'\/')}.#{video.type}", "w"){|f| f.write video.get_video}
              break if @q.empty?
              sleep 10
            }
          rescue => e
            @q.push sm_id unless e.inspect =~ /not found/
            puts e
            retry_cnt = retry_cnt + 1
            sleep 10*retry_cnt
            @client.login
            retry
          end
      }
      return t
    end
    def start_download
      (0..9).map{|i| t = self.worker;sleep 10*i;t }
    end
  end
end

マルチスレッドで

require 'mechanize'
downloader = Niconico::Downloader.new "takuyaXXXXXX**@gmail.com", "**password**" 
url = "http://www5.atwiki.jp/hmiku/pages/4386.html" 
 
m = Mechanize.new 
m.get url  
m.max_history = 2 
list = m.page.iframes.map{|e| e.src}.map{|e| e =~ /\/(sm[0-9]+)$/ ; $1} 
list.each{|e|  
  downloader.add_download_list e 
} 
 

threads = downloader.start_download
threads.map{|t| t.join}
puts :end

マルチスレッド版だから速いというわけ無く、単にマチスレッドを使って、ビデオIDをPostしたら待ちキューに入ってワーカーが淡々とダウンロードを繰り返す。これをつかって、drubyマチスレッドをポート指定で待ち受けてたり。