FRESH LIVEのコメントをDB化する

前回のブログで、コメント数ランキングなるものを発表しましたが、

これはFRESH LIVEが、OpenFRESH APIというものを公開してくれているので、
それを利用し、FRESH LIVEに投稿されたコメントを取得し、DB化することで実現しました。

仕組み

Node.jsを使って、OpenFRESH APIを叩き、MongoDBInsertしていきます。

const freshApi = 'https://openapi.freshlive.tv/v1/comments';
const request = require('request');
let programId = 123456;
let Lastmillisecond = -600000; // 放送開始10分前からコメントができるので、デフォルトの0だと取得漏れがある
request.get({
uri: freshApi,
headers: {
'Content-type': 'application/json'
},
qs: {
programId: programId,
limit: '500', // 500以上には設定できない
order: 'asc',
sinceMillisecond: Lastmillisecond
},
json: true
}, function (err, req, json) {
// 取得した後の処理
}
});

これでAPIから500件のコメントが取得できます(⊃∪`*)
500件以上のコメントが来ている場合は、
500件目のコメント(json.data[499])の投稿時間をsinceMillisecondに設定して再取得すると続きが拾えます。

この時、1回目の取得が終わってから、
その結果を考慮して次を取得開始しないといけないんですが、この同期的な処理がよくわからず苦戦しました(-_-)

コールバック地獄になってしまうので、Promiseというのを使うらしいのですが、ループのやり方がわからず、結局、、

freshApiPush('-600000').then(function(Lastmillisecond) {
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond);
}).then(function(Lastmillisecond){
return freshApiPush(Lastmillisecond); // と、、とりあえず最大15回(7500コメント)
}).catch(function(){
// ...
});

これでいいんですかね(笑)よくわかりません(-_-)
とりあえずうちの放送に来たコメント1枠最大で5000ちょいなので、これで全部拾えましたw

で、あとは取得したJSONをそのままMongoDBinsertManyします。
MongoDBならJSONを再整形しないでそのまま放り込めるので楽ですね(⊃∪`*)

const { MongoClient } = require('mongodb');
MongoClient.connect(mongoUrl, { useNewUrlParser: true }, (err, client) => {
if (err) throw err;
db = client.db(dbName);
// ...
db.collection('comments').insertMany(json.data, function (err, result) {
if (err) reject();
if (json.data.length >= 500) {
if (json.data[499].millisecond == json.meta.latestMillisecond) reject(); // 500ピッタリだったら止める
console.log('id:', programId, '/ +');
resolve(json.data[499].millisecond);
} else {
reject();
}
});
// ...
});

Promiseの中なので、reject/resolveで値を渡しています。
これでとりあえずProgramIdを渡せばコメントを取得するコードが書けました。

あとは、ProgramIdを配列で渡して全部まとめて処理させたいんですが、
Promiseが増えるとめんどくさいんで、一応非同期だしsetIntervalで(APIに負荷がかからないように)少しインターバル開けて繰り返し実行すればいいかなという感じにしました( ⁼̴̶̤̀ω⁼̴̶̤́ )

あとはMongoDB

db.getCollection('comments').aggregate([{ $group: { _id: "$freshId",count: { $sum: 1 } } },{ $sort: { count: -1 }} ])

こんな感じで実行すれば


このように簡単に投稿数ランキングが出せます(⊃∪`*)
他にも色んなことができそうですね!

いつも通りGitHub貼っておきますね(⊃∪`*)
https://github.com/tokjin/getCommentByFreshLive

※趣味でプログラム書いてますが、いつもネットで調べながら動けばいいというクソコードになっちゃってます。専門の方の優しいアドバイスなど頂けると嬉しいです(⊃∪`*)


あわせて読みたい

3件のフィードバック

  1. yyz より:

    Javascriptで非同期処理のループはえらい面倒でわかりにくいんですよね。
    だいぶ前ですが、.bind()でthisを渡してゴニョゴニョしてた気がします。今だともう少しやりやすくなってたりするんでしょうかな…?

    しかしこれは、ProgramIdも一緒にDBに保存すればその人の1配信あたりの平均コメント数とかもわかりそうですね…。自分はどのくらいなのやら。

    • じん より:

      勉強になります(⊃∪`*)ありがとうございます!
      実はOpenFRESH APIがProgramIdごと渡してくれているので、DBにも保存されています(⊃∪`*)
      というわけで調べてみました。

      db.getCollection(‘comments’).distinct(“programId”,{“freshId”: “2892094”}).length
      -> 366 // yyzさんがコメントした番組の数

      db.getCollection(‘comments’).find({“freshId”:”2892094″}).count()
      -> 18180 // yyzさんがコメントした合計数

      18180/366=49.6721311 // 1放送あたりの平均コメント数

      こんなに!!笑
      ありがとうございますm(_ _)m

  2. yyz より:

    うわーそんなにコメントしてましたかw
    まったく意識がないのが恐ろしいところですが、今後も意識せずにいきたいと思いますw

コメントを残す