FLYING

〈全日本・紀文豆乳飲料シリーズ「麦芽コーヒー」の500ミリリットルパックを扱う小売店が少ないことに遺憾の意を表明する会〉活動記録

添付ライブラリだけでニコニコ動画のFLVとXMLをダウンロード

もはや何番煎じか分からないネタ。ただし、添付ライブラリ以外は使わないってことにして差別化を図ってみた。なお、ニコニコAPIについては主に以下のページを参考にした。Geekな皆さんに感謝なのですよ、にぱ〜☆

鯖の健康を損なう恐れがあるため、使いすぎには注意しましょう。

うさげ

# ニコニコ動画にログイン
nico = Nico.new("YOUR_MAIL", "YOUR_PASSWORD")

まず、この部分にログイン用のメールアドレスとパスワードを記述し、保存してください。

ruby nico.rb smXXXXXXX

スクリプトを使うには、上のようにダウンロードしたい動画のIDを指定して実行します。

# FLVとXMLをダウンロード
print "video: #{nico.title.tosjis}\n"

ソース中にこんな行がありますが、環境によっては「tosjis」の部分を「toeuc」とか「toutf8」にする必要があるかもしれません。

ソース

# nico.rb

require 'cgi'
require 'uri'
require 'kconv'
require 'net/https'

class Nico
  attr_accessor :video, :video_id
  
  # ニコニコ動画にログイン
  def initialize(mail, password)
    https = Net::HTTP.new("secure.nicovideo.jp", 443)
    https.use_ssl = true
    https.start {|w|
      data = "site=niconico&next_url=&mail=#{mail}&password=#{password}"
      res = w.post("/secure/login", data)
      @sid = $1 if res["Set-Cookie"] =~ /user_session=user_session([0-9_]+)/
    }
  end
  
  # 動画の情報を取得
  def get_video(video_id)
    @video_id = video_id
    Net::HTTP.start("www.nicovideo.jp", 80) {|w|
      res = w.get("/api/getflv/#{@video_id}", "Cookie" => "user_session=user_session#{@sid}")
      array = CGI.unescape(res.body).split(/&/)
      array.map! {|e| e.split(/=/, 2) }
      @hash = Hash[*array.flatten]
    }
    # ダウンロードに必要なCookieを取得
    Net::HTTP.start("www.nicovideo.jp", 80) {|w|
      res = w.get("/watch/#{@video_id}", "Cookie" => "user_session=user_session#{@sid}")
      @history = $1 if res["Set-Cookie"] =~ /nicohistory=([^;]+)/
      @video = $1 if res.body =~ /<h1.*><a.*>(.*)<\/a><\/h1>/
    }
  end
  
  # 動画をダウンロード
  def get_flv
    uri = URI.parse(@hash["url"])
    res = nil
    Net::HTTP.start(uri.host, uri.port) {|w|
      res = w.get("#{uri.path}?#{uri.query}",
        "Cookie" => "user_session=user_session#{@sid}; nicohistory=#{@history}")
    }
    return res.body
  end
  
  # コメントをダウンロード
  def get_xml(comments)
    uri = URI.parse(@hash["ms"])
    res = nil
    Net::HTTP.start(uri.host, uri.port) {|w|
      data = "<thread user_id=\"#{@hash["user_id"]}\" res_from=\"#{comments}\""
      data += " version=\"20061206\" thread=\"#{@hash["thread_id"]}\" />"
      res = w.post(uri.path, data,
        "Cookie" => "user_session=user_session#{@sid}; nicohistory=#{@history}")
    }
    return res.body
  end
end

# ニコニコ動画にログイン
nico = Nico.new("YOUR_MAIL", "YOUR_PASSWORD")
nico.get_video(ARGV[0])
# FLVとXMLをダウンロード
print "video: #{nico.video.tosjis}\n"
print "saving video as #{nico.video_id}.flv ... "
open("#{nico.video_id}.flv", "wb") {|f| f.print nico.get_flv }
print "done.\n"
print "saving comments as #{nico.video_id}.xml ... "
open("#{nico.video_id}.xml", "w") {|f| f.print nico.get_xml(-100) }
print "done.\n"

追記 2008-03-26

あー、何故かコメントがダウンロードできなくなってるみたい。帰ってきたら直す。修正完了。POSTするデータのスペース入れ忘れが原因だったみたい。

追記 2008-04-06

動画個別ページの仕様変更に対応。