Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
54
Help us understand the problem. What is going on with this article?
@59naga

Nodejsでニコ生のコメビュを作る

More than 5 years have passed since last update.
d.hatena.ne.jp/toriimiyukki/20120124/1327417154
var net = require('net');
socket.connect(data.msPort, data.msAddr);
socket.setEncoding('utf-8');
socket.on('connect', function() {
    console.log('connected');
    socket.write('<thread thread="' + data.msThread + '" res_from="' + data.resFrom + '" version="20061206" >' + "\0");
});
socket.on('data', function(data) {
    console.log(data);
});

グーグルで検索すると見つかるこのコード片ではgetplayerstatusを取得しないので動きません。

  • 手動でAPIにアクセスして、該当箇所を書き換えると動きます。
    • data.msPort: <getplayerstatus><ms><port> の値
    • data.msAddr: <getplayerstatus><ms><addr> の値
    • data.msThread: <getplayerstatus><ms><thread> の値
    • data.resFrom: -1000~0 コメント開始位置

suck.js
var net= require('net');
var socket= net.connect(2811,'omsg101.live.nicovideo.jp');
socket.on('connect', function(){
  console.log('connected');
  socket.setEncoding('utf-8');
  socket.write('<thread thread="1435806943" res_from="-5" version="20061206" />\0');
});
socket.on('data',function(data){
  console.log(data);
});
data
<thread resultcode="0" thread="1435806943" last_res="2836" ticket="0x1dfc9b00" revision="1" server_time="1431262237"/><chat thread="1435806943" vpos="6450700" date="1431261909" date_usec="57301" mail="184" user_id="Idj1TdXOGrERXdFOUdiTX4sKIB0" anonymity="1" locale="jp">v(゚Д゚)v<♪ カァーニー カァーニー ショヌダー カジカジ バーブー ソムダー パッ! ♬</chat><chat>...</chat>

This sucks.
この記事では、ログインから順を追って説明します。

ログイン

https://secure.nicovideo.jp/secure/loginmail_telpasswordPOSTします。
requestモジュールを使用します。

$ npm install request
$ node login.js
login.js

var request= require('request');

request.post({
  url: 'https://secure.nicovideo.jp/secure/login',
  form: {
    mail_tel: 'your@mail.address',
    password: '********',
  },
},function(error,response){
  if(error!=null) throw error;

  var session= null;
  var cookies= response.headers['set-cookie'] || [];
  for(var i=0; i<cookies.length; i++){
    var cookie= cookies[i];
    if(cookie.match(/^user_session=user_session/)){
      session= cookie.slice(0,cookie.indexOf(';')+1);
    }
  }

  console.log(response.headers['set-cookie']);
  console.log(session);
});

ログインが正常であれば

response.headers['set-cookie']

[ 'nicosid=1431257919.1222609129; expires=Wed, 07-May-2025 11:38:39 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=user_session_000000_0000000000000000000000000000000000000000000000000000000000000000; expires=Tue, 09-Jun-2015 11:38:39 GMT; path=/; domain=.nicovideo.jp',
  'repair_history=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.nicovideo.jp' ]
session
user_session=user_session_000000_0000000000000000000000000000000000000000000000000000000000000000;

のような値が返ります。最終的に使用するのはsessionのみです。

以降はこのsessionを使いまわします。sessionはしばらく有効で、ローカルファイルとして値を保存しておくことで、メソッド毎にログイン処理を挟まずに済むでしょう。

プレイヤー(コメントサーバー)情報の取得

では早速、getplayerstatusが使用可能になったことを確認しましょう。

getplayerstatus.js
var request= require('request');
request({
  url: 'http://live.nicovideo.jp/api/getplayerstatus/nsen/hotaru',
  headers: {
    Cookie: session,
  },
},function(error,response){
  if(error!=null) throw error;

  console.log(response.body);
});
response.body
<?xml version="1.0" encoding="utf-8"?>
<getplayerstatus status="ok" time="1431262800"><stream><id>lv220580424</id><title>Nsen - 蛍の光チャンネル</title><description>Nsenからの去り際に自主的にお立ち寄り下さい。Nsenをご堪能頂いた後、また、ネットサーフィンを終え眠りにつく時などにオススメです。</description>...</stream>
...
<ms><addr>omsg101.live.nicovideo.jp</addr><port>2811</port><thread>1435806943</thread></ms>
...
</getplayerstatus>

プレイヤー(コメントサーバー)情報を取得することができました。

getplayerstatusは nsen, lv***, co***の3種類が使用可能です。

cheerioモジュールを使用して、必要な値だけを取り出します。

$ npm install cheerio
$ node getplayerstatus.js
getplayerstatus.js
var request= require('request');
var cheerio= require('cheerio');

request({
  url: 'http://live.nicovideo.jp/api/getplayerstatus/nsen/hotaru',
  headers: {
    Cookie: session,
  },
},function(error,response){
  if(error!=null) throw error;

  var $= cheerio.load(response.body);
  console.log($('getplayerstatus ms port').text());
  console.log($('getplayerstatus ms addr').text());
  console.log($('getplayerstatus ms thread').text());
});
console.log
2811
omsg101.live.nicovideo.jp
1435806943

プレイヤーへ接続する

これまでのコードを繋ぎあわせて、コメントを取得します。

nicolive.js
// Dependencies
var request= require('request');
var cheerio= require('cheerio');
var net= require('net');

// Demonstration
process.nextTick(function(){
  // Environment
  var id= 'your@mail.address';
  var pw= '********';
  var live_id= 'nsen/hotaru';

  // Boot
  nicolive.login(id,pw,function(error,session){
    if(error!=null) throw error;

    nicolive.fetchThread(live_id,session,function(error,thread){
      if(error!=null) throw error;

      nicolive.view(thread,function(error,viewer){
        if(error!=null) throw error;

        viewer.on('data',function(data){
          console.log(data);
        });
      });
    });
  });
});

// Methods
nicolive= {
  login: function(id,pw,callback){
    request.post({
      url: 'https://secure.nicovideo.jp/secure/login',
      form: {
        mail_tel: id,
        password: pw,
      },
    },function(error,response){
      if(error!=null) return callback(error);

      var session= null;
      var cookies= response.headers['set-cookie'] || [];
      for(var i=0; i<cookies.length; i++){
        var cookie= cookies[i];
        if(cookie.match(/^user_session=user_session/)){
          session= cookie.slice(0,cookie.indexOf(';')+1);
        }
      }
      if(session==null) return callback(new Error('Invalid user'));

      callback(null,session);
    });
  },
  fetchThread: function(live_id,session,callback){
    request({
      url: 'http://live.nicovideo.jp/api/getplayerstatus/'+live_id,
      headers: {
        Cookie: session,
      },
    },function(error,response){
      if(error!=null) return callback(error);

      var $= cheerio.load(response.body);
      callback(null,{
        port: $('getplayerstatus ms port').text(),
        addr: $('getplayerstatus ms addr').text(),
        thread: $('getplayerstatus ms thread').text(),
      });
    });
  },
  view: function(thread,callback){
    var viewer= net.connect(thread.port,thread.addr);
    viewer.on('connect', function(){
      viewer.setEncoding('utf-8');
      viewer.write('<thread thread="'+thread.thread+'" res_from="-5" version="20061206" />\0');

      callback(null,viewer);
    });
  },
}

module.exports= nicolive;
$ node nicolive.js
console.log(data);
<thread resultcode="0" thread="1435806943" last_res="2836" ticket="0x1dfc9b00" revision="1" server_time="1431262237"/><chat thread="1435806943" vpos="6450700" date="1431261909" date_usec="57301" mail="184" user_id="Idj1TdXOGrERXdFOUdiTX4sKIB0" anonymity="1" locale="jp">v(゚Д゚)v<♪ カァーニー カァーニー ショヌダー カジカジ バーブー ソムダー パッ! ♬</chat><chat>...</chat>

成果物(Electron製コメントビューアー)

d06cf958-ebda-11e4-9d22-5f9420129523.png

参考

54
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
59naga
趣味で即物的な記事を書きます

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
54
Help us understand the problem. What is going on with this article?