ニコニコ動画ってapiあったの!?
あれ、簡単にコメントだけ取得してくれないの?
くそ、こうなったら作るか、、、
極力gemに頼らないぜ!
というわけで、なかなかに不親切なニコニコ動画のapiと戦っていた。
どうやら、ニコニコ動画のコメントをapi経由で手に入れるには3段階必要で、
1.ニコニコ動画にログイン
2.getflv apiにgetしてスレッドIDなど取得
3.msg.nicovideo.jpにpostしてコメントxml取得
ということらしいです。
まず、ニコニコ動画にログイン、ということで、
https://secure.nicovideo.jp/secure/login?site=niconico
に、自分のメールアドレスとパスワードをpostします。
httpsです。セキュアです。
すると、なんかuser_sessionとかいうクッキーがやたらと帰ってくるので、
その中から、deletedになっていないクッキーを抽出します。
というわけで、メールアドレスとパスワードを渡すと、必要なクッキーを返してくれるものを作った。
# ログインしてクッキー抽出
def login_nicovideo(mail, pass)
host = 'secure.nicovideo.jp'
path = '/secure/login?site=niconico'
body = "mail=#{mail}&password=#{pass}"
https = Net::HTTP.new(host, 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = https.start { |https|
https.post(path, body)
}
cookie = ''
response['set-cookie'].split('; ').each do |st|
if idx=st.index('user_session_')
cookie = "user_session=#{st[idx..-1]}"
break
end
end
return cookie
end
次に、ニコニコ動画のapiであるgetflvを使います。
下のURLに、さっき選別したクッキーを一緒にgetします。
http://flapi.nicovideo.jp/api/getflv/#{動画ID sm**とか}
すると、以下のような動画情報が帰ってくるので、
お好みで整形します。
今回はハッシュにぶち込み。
でも結局、使うのはthread_idとmsだけなんだよね。
# レスポンス
{:thread_id=>"1173108780",
:l=>"320",
:url=>"http%3A%2F%2Fsmile-pcm00.nicovideo.jp%2Fsmile%3Fv%3D9.0468",
:link=>"http%3A%2F%2Fwww.smilevideo.jp%2Fview%2F9%2F1175906",
:ms=>"http%3A%2F%2Fmsg.nicovideo.jp%2F10%2Fapi%2F",
:user_id=>"1175906",
:is_premium=>"1",
:nickname=>"%E7%81%B0%E5%AD%90",
:time=>"1311177690",
:done=>"true",
:hms=>"hiroba04.nicovideo.jp",
:hmsp=>"2526",
:hmst=>"1000000062",
:hmstk=>"1311177750.c-1OX5rNY8K94qGGdSstdX6BZV0",
:rpu=> "%7B%22count%22%3A1330527%2C%22users%22%3A%5B%22%5Cu30b7%5Cu30a2%22%2C%22%5Cu6771%5Cu96f2%22%2C%22%5Cu307a%5Cu30fc%5Cu3061%5Cu3083%5Cu3093%22%2C%22murayuu%22%2C%22%5Cu30ad%5Cu30e3%5Cu30a4%5Cuff5e%5Cu30f3%22%2C%22%5Cu30a2%5Cu30eb%22%2C%22%5Cu3072%5Cu3055%22%2C%22%5Cu305f%5Cu308d%5Cu308d%22%2C%22orycteropus%22%2C%22%5Cu3086%5Cu3063%5Cu3053%22%2C%22%5Cu3042%5Cu3064%5Cu3054%5Cu3093%22%2C%22%5Cu9577%5Cu8c37%5Cu5ddd%5Cu30fb%5Cu30b8%5Cu30e3%5Cu30b3%5Cu30b3%22%2C%22%5Cu307e%5Cu30fc%5Cu304f%5Cu3093%22%2C%22%5Cu304b%5Cu3055%22%2C%22%5Cu3072%5Cu3055%22%2C%22%5Cu653e%5Cu8ab2%5Cu5f8c%22%2C%22%5Cu5fd8%5Cu308c%5Cu3058%5Cu3083%5Cu3044%5Cu3063%22%2C%22%5Cu308a%5Cu3087%5Cu3046%22%2C%22%5Cu304d%5Cu3061%5Cu304f%5Cu3093%22%2C%22getsu%22%5D%2C%22extra%22%3A20%7D"}
# getflvから動画情報取得
def get_flv_info(cookie, video_id)
host = 'flapi.nicovideo.jp'
path = "/api/getflv/#{video_id}"
response = Net::HTTP.new(host).start { |http|
request = Net::HTTP::Get.new(path)
request['cookie'] = cookie
http.request(request)
}
flv_info = {}
response.body.split('&').each do |st|
stt = st.split('=')
flv_info[stt[0].to_sym] = stt[1]
end
flv_info[:ms] =~ /(http%3A%2F%2Fmsg\.nicovideo\.jp%2F)(.*?)(%2Fapi%2F)/
flv_info[:msg] = $2
return flv_info
end
そして最後に、さっきのレスポンスにあったmsへ、xmlをpostします。
msは以下みたいな感じ
http://msg.nicovideo.jp/10/api/
xmlの内容は、
<thread thread="" version="" res_from="">
threadは、さっきのレスポンスにあったthread_id
versionは、20061206の固定値らしい。
res_fromは取得コメント数。500件ほしかったら、-500 と入れよう!
結果はxmlで帰ってくるので、
オリジナルでコメント部分だけ抽出しちゃいます。
というわけで、コメントの配列を返すものを作った。
# コメントを取得してコメントの配列を返す
def get_comments(flv_info, res_from)
host = 'msg.nicovideo.jp'
path = "/#{flv_info[:msg]}/api/"
response = Net::HTTP.new(host).start { |http|
request = Net::HTTP::Post.new(path)
request.body = '<thread thread="'+flv_info[:thread_id]+'" version="20061206" res_from="-'+res_from.to_s+'">'
http.request(request)
}
comments = []
xml = response.body.gsub('</chat>', "</chat>\n")
xml.split("\n").each do |line|
if line =~ /<chat.*?>(.*?)<\/chat>/
comments << $1
end
end
return comments
end
ちまちま睡眠時間削って早1週間、
長かったぜ・・・。
では、上記の部品を使った例として、
sm9のコメントを100件取得するrubyプログラムはこちら。
自分のメールアドレスとパスワードで試してね。
# やっぱsm9か
require 'net/https'
def login_nicovideo(mail, pass)
host = 'secure.nicovideo.jp'
path = '/secure/login?site=niconico'
body = "mail=#{mail}&password=#{pass}"
https = Net::HTTP.new(host, 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = https.start { |https|
https.post(path, body)
}
cookie = ''
response['set-cookie'].split('; ').each do |st|
if idx=st.index('user_session_')
cookie = "user_session=#{st[idx..-1]}"
break
end
end
return cookie
end
def get_flv_info(cookie, video_id)
host = 'flapi.nicovideo.jp'
path = "/api/getflv/#{video_id}"
response = Net::HTTP.new(host).start { |http|
request = Net::HTTP::Get.new(path)
request['cookie'] = cookie
http.request(request)
}
flv_info = {}
response.body.split('&').each do |st|
stt = st.split('=')
flv_info[stt[0].to_sym] = stt[1]
end
flv_info[:ms] =~ /(http%3A%2F%2Fmsg\.nicovideo\.jp%2F)(.*?)(%2Fapi%2F)/
flv_info[:msg] = $2
return flv_info
end
def get_comments(flv_info, res_from)
host = 'msg.nicovideo.jp'
path = "/#{flv_info[:msg]}/api/"
response = Net::HTTP.new(host).start { |http|
request = Net::HTTP::Post.new(path)
request.body = '<thread thread="'+flv_info[:thread_id]+'" version="20061206" res_from="-'+res_from.to_s+'">'
http.request(request)
}
comments = []
xml = response.body.gsub('</chat>', "</chat>\n")
xml.split("\n").each do |line|
if line =~ /<chat.*?>(.*?)<\/chat>/
comments << $1
end
end
return comments
end
cookie = login_nicovideo('自分のメールアドレス', '自分のパスワード')
flv_info = get_flv_info(cookie, 'sm9') # sm9からコメントを
comments = get_comments(flv_info, 100) # 100件取得
# コメント表示してるだけ
comments.each do |com|
puts com
end
以上。