如何在Node JS函数中检查JSON对象的元素中的空值?

时间:2019-02-20 02:03:37

标签: node.js json

我正在使用node.js中的google-play-scraper模块来抓取Google Play评论。单个页面的查看功能如下:

var gplay = require('google-play-scraper');
gplay.reviews({
  appId: 'es.socialpoint.chefparadise',
  page: 0,
  }).then(console.log, console.log);

现在,我想一次在所有页面上抓取所有评论,并将其保存在记录器中。为此,我正在使用winston logger和如下的for循环:

var gplay = require('google-play-scraper');
const winston= require('winston');

  const logger = winston.createLogger({
    transports: [
      new winston.transports.Console(),
      new winston.transports.File({ filename: 'rev1.log' })
   ]
  });
package_id='com.jetstartgames.chess'
for (i=0; i<112; i++){

    gplay.reviews({
    appId: package_id,
    page: i,
    }).then(logger.info, logger.info); 
}

问题是我应该为每个应用程序预定义其评论所拥有的最大页面数(我应该为循环确定i的最大值)。为了做到这一点,我教过检查空值,但是我找不到可行的方法。实际不存在的页面的日志文件具有以下结构:

{“消息”:[],“级别”:“信息”}

我尝试了以下无效的代码:

max=0
for (i=0; i<10000; i++){
 data=gplay.reviews({
    appId: 'com.jetstartgames.chess',
    page: i,
    });
    if (data.message==null || data.message==undefined){
        break;
    } else {
        max+=1;
    }
}

是否可以通过检查第一个空输出来找出最大页数?或为此目的有其他建议吗?

3 个答案:

答案 0 :(得分:0)

所以有两个问题,您使用的api似乎使用了Promises,因此返回值直到进一步循环时才可用。

如果您使用的是node.js> 7.6,则可以这样使用async / await;

import gplay from 'google-play-scraper';

async function getReviews(appId, page = 1) {
  return await gplay.reviews({
    appId,
    page,
  });
}

async function process(appId) {
  let page = 1;
  let messages = [];
  let result;

  do {
    result = await getReviews(appId, page);
    messages = messages.concat(result);
    ++page;
  } while (result.length > 0);

  return messages;
}

process('com.jetstartgames.chess')
.then((messages) => {
  console.log(messages);
})

答案 1 :(得分:0)

我尝试这样实现。请尝试让我知道是否可行:)

reviews的文档中,请注意:

  

请注意,此方法以特定语言(英文)返回评论   默认情况下),因此您需要尝试其他语言才能获得更多   评论。另外,在Google Play页面中显示的计数器是指   应用程式拥有的1-5星评分总数,而不是   书面评论计数。因此,如果该应用程序的评级为100k,请不要期望   使用此方法可获得10万条评论。

var gplay = require('google-play-scraper');
    var appId = 'com.jetstartgames.chess';
    var taskList = [];

    for(var i = 1 ; i < 10000; i++){
        taskList.push(new Promise((res, rej)=>{
            gplay.reviews({
                appId: appId,
                page: i,
                sort: gplay.sort.RATING
            }).then(result =>{
                res(result.length);
            })
            .catch(err => rej(err)) 
        }));
    }

    Promise.all(taskList)
    .then(results => {
        results = results.filter(x => x > 0);
        var maxPage = results.length;
        console.log('maxPage', maxPage);
    })
    .catch(err => console.log(err))

答案 2 :(得分:0)

  

问题是我应该为每个应用程序预定义其评论的最大页数(我应该为循环确定i的最大值)。

我认为我们可以从app响应中获取此数据。

{
  appId: 'es.socialpoint.chefparadise',
  ...
  ratings: 27904,
  reviews: 11372, // data to determine pagenumber
  ...
}

此外,review为页码计算提供了一个停球场编号。

  

页面(可选,默认为0):包含评论的页面数。每个页面最多有40条评论。

进行这些更改,

'use strict';

const gplay = require('google-play-scraper');
const packageId = 'es.socialpoint.chefparadise';

function getAppDetails(packageId) {
  return gplay.app({ appId: packageId })
    .catch(console.log);
}

getAppDetails(packageId).then(appDetails => {
  let { reviews, ratings } = appDetails;

  const totalPages = Math.round(reviews / 40);

  console.log(`Total reviews => ${reviews} \nTotal ratings => ${ratings}\nTotal pages => ${totalPages} `);

  let rawReview = [];

  let pageNumber = 0;
  while (pageNumber < totalPages) {
    console.log(`pageNumber =${pageNumber},totalPages=${totalPages}`);
    rawReview.push(gplay.reviews({
      appId: packageId,
      page: pageNumber,
    }).catch(err => {
      console.log(packageId, pageNumber);
      console.log(err);
    }));
    pageNumber++;
  }

  return Promise.all(rawReview);
}).then(reviewsResults => {
  console.log('***Reviews***');
  for (let review of reviewsResults) {
    console.log(review);
  }
}).catch(err => {
  console.log('Err ', err);
});

对于带有较少评论的packageId来说效果很好。但是对于es.socialpoint.chefparadise,由于数据量巨大,我经常遇到Issue #298

输出

  

总评论=> 215922
  总评分=> 688107
  总页数=> 5398
   评论
  ....