LoginSignup
6
6

More than 5 years have passed since last update.

AppStore,GooglePlayの昨日のレビューをまとめてメール送信

Last updated at Posted at 2016-04-26

概要

リリースしているアプリが多いと、レビューのチェックとか大変じゃないですか?

ってことで、前日のレビューをまとめてメールで送ってくるスクリプトをGASで書いてみました!

AppStoreは、レビュー取得のAPIを使いましたが、GooglePlayにはAPIがないのでスクレイピングしてます。
なので、GooglePlayのフォーマットが変わったりすると修正する必要があります。

レビューメールサンプル

こんな感じで、前日のレビューのみを抽出したメールが毎日送られてきます。

■
■ GooglePlay : 激Jパチスロ 2027
■ https://play.google.com/store/apps/details?id=jp.dorasu.apps.and2027
■

2016/3/31 ××××
何もできません ★☆☆☆☆
 落としたけどいきなり停止 何もできません お金も取られたまんま 安売りの罠


■
■ GooglePlay : 激Jパチスロ BLACK LAGOON
■ https://play.google.com/store/apps/details?id=jp.dorasu.apps.blacklagoon
■

2016/3/31 □□□□
 ★★★★★
 懐かしくてよかった


■
■ AppStore : 激Jパチスロ BLACK LAGOON 2
■ https://itunes.apple.com/jp/app/jijpachisuro-black-lagoon-2/id961851134?mt=8&uo=2
■

2016/03/31 11:24:00 はざず
はあ ★★★★★
おもろい


■
■ AppStore : 激Jパチスロ HIGHSCHOOL OF THE DEAD
■ https://itunes.apple.com/jp/app/jijpachisuro-highschool-dead/id684256528?mt=8&uo=2
■

2016/03/31 08:11:00 らゆなさ
よい ★★★★☆
よいよ、よい

2016/03/31 00:40:00 △△サダオシ
なかなか良い ★★★★☆
実機にかなり近いクオリティー。

レビューをとってくるアプリの指定

アプリIDをB列の2行目から記載したリストを作成します。
スクリプトで使うのはB列のみです。

AppStoreとGooglePlayは別のシートで作成し、シート名をスクリプトで指定します。

シートAppStore-Screenshot.png

シートGooglePlay-Screenshot.png

コード

コード.GS
//
// 昨日のアプリレビューをメール送信する
//
function sendMailYesterdayReview() {

  //スプレッドシートに記載のアプリIDのレビューを取得、整形
  var text = "";
  text += jobSheet("GooglePlay", "Dorasu GooglePlay");
  text += jobSheet("AppStore", "Dorasu AppStore");

  //取得したレビューをメール送信
  var MAIL_TO    = "XXXX@XXXXX.XXXX,YYYY@YYYYY.YYY";
  var MAIL_TITLE = "アプリレビュー";
  if (text != "") {
    MailApp.sendEmail(MAIL_TO, MAIL_TITLE, text);
    Logger.log("メール送信 to:"+MAIL_TO+"  title:"+MAIL_TITLE+"\n"+text);
  } else {
    Logger.log("昨日分のレビューがないのでメール送信はしませんでした。");
  }
}


// 1シート分の処理
function jobSheet(type, sheetName)
{
  var ROW_START = 2;  //IDが入っている行の開始位置
  var COL_ID    = 2;  //IDが入っている列

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  var values = sheet.getDataRange().getValues();

  Logger.log("シート["+sheetName+"] 処理開始");

  var cnt=0;
  var text = "";
  for(var i = ROW_START-1; i < values.length; i++){    
    var id = values[i][COL_ID-1];
    text += jobTitle(type, id);
    cnt++;
  } 

  Logger.log("シート["+sheetName+"] "+cnt+"タイトル処理終了");

  return text;
}

// 1タイトル分の処理
function jobTitle(type, id)
{
  var result;
  var text = "";

  //レビューをとってくる
  if (type == "AppStore") {
    result = fetchReviewAppStore(id);
    result.type = "AppStore";
  } else {
    result = fetchReviewGooglePlay(id);
    result.type = "GooglePlay";
  }

  //エラー
  if (result.error) {
    text = "ERROR : " + result.url + "\n";
    Logger.log(text);
    return text;
  }

  //昨日のレビューのみを抽出
  var date = new Date();
  date.setDate(date.getDate()-1);
  result.reviews = extractReviewByDate(result.reviews, date);

  if (result.reviews.length > 0) {
    //タイトル
    text += "\n";
    text += "\n";
    text += "" + result.type + " : " + result.title + "\n";
    text += "" + result.link + "\n";
    text += "\n";
    text += "\n";

    //レビューを新しい順にソートして追加
    result.reviews.sort((function(a,b){return(new Date(b.date).getTime() - new Date(a.date).getTime());}));
    text += formatReview(result.reviews);

  }

  Logger.log(id+" "+result.title+" "+result.reviews.length+"レビュー");

  return text;
}


//レビューを整形
function formatReview(reviews)
{
  var text = "";

  for (var i in reviews) {
    text = text + reviews[i].date + " " + reviews[i].author + "\n";
    text = text + reviews[i].title + " " + ("★★★★★☆☆☆☆☆").substr(5-reviews[i].rating, 5) + "\n";
    text = text + reviews[i].content + "\n";
    text = text + "\n";
  }

  return text;
}

//指定日のレビューのみ抽出
function extractReviewByDate(reviews, date)
{
  var result = [];

  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);
  date.setMilliseconds(0);

  for (var i in reviews) {
    var d = new Date(reviews[i].date);
    d.setHours(0);
    d.setMinutes(0);
    d.setSeconds(0);
    d.setMilliseconds(0);
    if (d.getTime() == date.getTime()) {
      result.push(reviews[i]);
    }
  }

  return result;
}



// AppStoreからレビュー取得
function fetchReviewAppStore(id) {
  var url = "https://itunes.apple.com/jp/rss/customerreviews/id=" + id + "/xml";
  var query = 'select * from xml where url="' + url + '"';
  var response = UrlFetchApp.fetch("https://query.yahooapis.com/v1/public/yql?format=json&q="+encodeURIComponent(query),{'muteHttpExceptions':true});
  try {
    var entrys = JSON.parse(response).query.results.feed.entry;
    var result = {};
    var review = [];

    for (var entry in entrys) {
      if (entry == 0) {
        result.title = entrys[entry].name;
        result.link  = entrys[entry].link.href;
      }
      else {
        review.push({
          date:    entrys[entry].updated.replace(/(.*?)-(.*?)-(.*?)T(.*?)-.*/,"$1/$2/$3 $4"),
          title:   entrys[entry].title,
          content: entrys[entry].content[0].content,
          rating:  entrys[entry].rating,
          version: entrys[entry].version,
          author:  entrys[entry].author.name
        });
      }
    }
    result.reviews = review;
    return result;
  } catch (e) {
    return {
      error:   true,
      title:   "",
      link:    url,
      reviews: review
    };
  }    
}


// GooglePlayからレビュー取得
function fetchReviewGooglePlay(id) {
  var url      = "https://play.google.com/store/apps/details?id=" + id;
  var response = UrlFetchApp.fetch(url,{'muteHttpExceptions':true});
  try {
    var result = {};
    var review = [];

    result.error = false;

    var regexp   = /<div class=\"id-app-title\".+?<\/div>/gi;
    var elements = response.getContentText().match(regexp);
    result.title = elements[0].replace(/.*?>(.*?)<.*/,"$1");
    result.link  = url;

    var regexp   = /<div class=\"single-review\".+?class=\"review-link\"/gi;
    var elements = response.getContentText().match(regexp);
    for (var i in elements) {
      review.push({
        author:     elements[i].replace(/.*<span class=\"author-name\">.*?>(.*?)<.*/,"$1"),
        date:       elements[i].replace(/.*<span class=\"review-date\">(.*?)(.*?)(.*?)日.*/,"$1/$2/$3"),
        title:      elements[i].replace(/.*<span class=\"review-title\">(.*?)<.*/,"$1"),
        content:    elements[i].replace(/.*<span class=\"review-title\">.*?>(.*?)<.*/,"$1"),
        rating:     elements[i].replace(/.*aria-label=\"5つ星のうち(.*?)つ星で評価しました.*/,"$1")

      });
    }
    result.reviews = review;

    return result;
  } catch(e) {
    return {
      error:   true,
      title:   "",
      link:    url,
      reviews: review
    };
  }
}
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6