Create a gist now

Instantly share code, notes, and snippets.

ニコ動のマイリストをマイリストページのRSSから取得するやつ
"use strict"
const http = require("http");
const fs = require("fs");
const cheerio = require("cheerio");
// コマンドの引数を受け取って処理
if (process.argv.length < 3) {
console.log("マイリストIDを指定してください");
} else {
var id = process.argv[2],
user_session = (process.argv[3])?process.argv[3]:"";
getMylistFromRss(id, user_session).then(function (result) {
var fileName = "mylist_" + id + ".json";
console.log("タイトル: "+result.title);
console.log("アイテム数: "+result.item.length);
fs.writeFile(
fileName,
JSON.stringify(result, null, " ")
);
console.log("\"" + fileName + "\"に出力しました");
}).catch(function (error) {
console.log(error);
});
}
/**
* HTTPでヘッダーも含めて取得してPromiseで返す
* @param {Object} options - http.requestで使うオプション
* @return {Promise}
*/
function getByHttp (options) {
return new Promise(function (resolve, reject) {
var req = http.request(options, function (res) {
res.setEncoding("utf8");
var temp = "";
if (res.statusCode < 200 || res.statusCode > 299) {
reject(new Error(res.statusCode));
}
res.on("data", function (chunk) {
temp += chunk;
});
res.on("end", function () {
resolve({
headers: res.headers,
body: temp
});
});
});
req.on("error", function (error) {
reject(error);
});
req.end();
});
}
/**
* マイリストを取得してPromiseで返す
* @param {String} id - マイリストID
* @return {Promise}
*/
function getMylistFromRss (id, user_session) {
return new Promise(function (resolve, reject) {
getByHttp({
hostname: "www.nicovideo.jp",
path: "/mylist/"+id+"?rss=2.0",
port: 80,
method: "GET",
headers: {
"Cookie": "user_session="+user_session+";"
}
}).then(function (result) {
resolve(getMylistData(result.body));
}).catch(function (error) {
reject(error);
});
});
}
/**
* RSSからマイリストデータを生成
* @param {String} xml - RSSの文字列
* @return {Object}
*/
function getMylistData (xml) {
var $ = cheerio.load(xml, { xmlMode: true}),
ret = {
id: "",
title: "",
description: "",
creator: "",
item: []
};
// マイリストタイトル
var title = $("channel > title").text()
.match(/^.+?\s(.+)\u2010[^\u2010]+?$/);
if (!title || title.length-1 > 1) {
ret.title = "No title";
} else {
ret.title = title[1];
}
// マイリスト説明
ret.description = $("channel > description").text();
// マイリスト所有者
ret.creator = $("channel > dc\\:creator").text();
// 非公開ならここで返す
if (!ret.creator) {
ret.title = "このマイリストは非公開です";
return ret;
}
// マイリストID
var id = $("channel > link").text().split("/");
if (!id) return ret;
ret.id = id.slice(-1)[0];
// マイリストアイテム
$("channel > item").each(function (i, elem) {
var item_data = {
title: "",
video_id: "",
thumbnail_url: "",
length_seconds: 0
};
var description = $(this).children("description").text();
// タイトル
item_data.title = $(this).children("title").text();
// ID
item_data.video_id =
$(this).children("link").text().split("/")[4];
// サムネイルURL
item_data.thumbnail_url =
description.match(/http:\/\/.+\.smilevideo\.jp\/smile\?i=[0-9]+/)[0];
// 再生時間(秒)
item_data.length_seconds = 0;
var length_second =
description.match(/<strong class="nico-info-length">([0-9|:]+?)<\/strong>/);
if (length_second && length_second[1]) {
length_second = length_second[1].split(":");
length_second = (length_second[0]-0)*60+(length_second[1]-0);
item_data.length_seconds = length_second;
}
// 配列に追加
ret.item.push(item_data);
});
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment