カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

Rubyとnet/httpsライブラリを使用してニコニコ動画にログインする

前の投稿で試してみたニコニコ動画のgetthumbinfo APIはログインを必要としませんでした。しかし、参考ページによると他のAPIはログインが必要です。なのでRuby 2.0.0とnet/httpsライブラリでニコニコ動画にログインするコードを書いてみました。最初にコードを示します。

require 'net/https'

module NicovideoAPIWrapper extend self
    def login(mail, password)
        #ログインを試みる
        https = Net::HTTP.new('secure.nicovideo.jp', 443)
        https.use_ssl = true
        https.verify_mode = OpenSSL::SSL::VERIFY_NONE
        response = https.start{|https|
            https.post('/secure/login?site=niconico', "mail=#{mail}&password=#{password}")
        }

        #set-cookieには複数のcookieが設定されている。
        #user_sessionがdeletedでない最初のcookieを探す。
        user_session = nil
        response.get_fields('set-cookie').each {|cookie|
            cookie.split('; ').each {|param|
                pair = param.split('=')
                if pair[0] == 'user_session' then
                    user_session = pair[1] if pair[1] != 'deleted'
                    break
                end
            }
            break unless user_session.nil?
        }       
        return user_session
    end
end
user_session = NicovideoAPIWrapper::login('<ニコニコ動画の登録メールアドレス>', '<ニコニコ動画のパスワード>')
puts "有効なセッションID:#{!user_session.nil? ? user_session : '<None>'}"

全体としてはHTTPSでPOSTしてset-cookieを受け取り、そこからログインが必要なAPIで使う有効なuser_sessionを取り出しています(詳しくは下の方で)。

NicovideoAPIWrapper::loginの前半、net/httpsでログインページにPOSTしてcookieを取得するまではnet/httpsのドキュメントにあるサンプルコードとほぼ一緒です。もちろん同期処理とかしていないので実行すると一時停止します。後半のコードはcookieをごたごた扱っています。実際には参考にさせて頂いたページの様にsplitで切り分けてindexした方が早いと思います。

これでログインが必要なニコニコ動画APIも使えるはずです。ちょこちょこと追加していけたら嬉しいです。ちなみに参考にしたページと同じで依存関係は最低限にしたいのでnet/httpsを使いましたが、他にも公開ライブラリを使用したログイン方法がいくつもあるそうです。検索すればすぐに見付かると思います。

ログインページから返されるset-cookieの内容

ニコニコ動画のログインページにメールアドレスとパスワードをPOSTした時、get_fields('set-cookie')はcookieの配列を返しますが、そこにはuser_session=deletedの無効なuser_sessionが複数含まれます。具体的には以下の通りです(hogeとかfugaは誤魔化し部分です)。

require 'net/https'
require 'pp'

mail     = '<ニコニコ動画の登録メールアドレス'
password = '<ニコニコ動画のパスワード>'

https = Net::HTTP.new('secure.nicovideo.jp', 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = https.start{|https|
    https.post('/secure/login?site=niconico', "mail=#{mail}&password=#{password}")
}
pp response.get_fields('set-cookie')
=> ["nicosid=hoge.hoge; expires=Wed, 27-Dec-2023 09:50:19 GMT; path=/; domain=.nicovideo.jp",
 "user_session=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT",
 "user_session=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/",
 "user_session=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.nicovideo.jp",
 "user_session=fuga; expires=Tue, 28-Jan-2014 09:50:20 GMT; path=/; domain=.nicovideo.jp",
 "repair_history=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.nicovideo.jp"]