GASとスプレッドシートで昨日のRSSフィードをメールに送信する方法

GoogleAppsScript

今回は、GoogleAppsScriptとGoogleスプレッドシートを用いて、昨日更新分のRSSフィードをメールに送信するというスクリプトを作成しました。

こういった処理はIFTTTや各種RSSリーダーを用いれば事足りそうですが、グーグルアラート好きな私としては、それに似た形式で情報を見たかったので、仕方なく、自作することにしました。

少し紹介しておきます。

 

はじめに

まずは、このスクリプトを用いることでどんな事ができるか紹介します。

以下のような、サイト名とRSSリンクのリストが入力されたスプレッドシートがあった場合に、スクリプトを実行すると、昨日発行分の記事が一覧となってメールに送信されます。

 

 

メールはこんな感じ。

 

 

スプレッドシートを用意しよう

まずは、スプレッドシートを用意してください。

  • A列にはサイト名(これがメールの件名になります)
  • B列にはRSSリンク

をそれぞれ入力します。

また、シート名は、わかりやすくするために「RSSシート」と変更しておいてください。

1行目はタイトルとするので、それぞれのタイトルを入力してください。

以下のような感じです。

 

 

この画像では、サイトを1つしか設定していませんが、スクリプトは、サイトが複数になっても対応できるようになっています。なので、複数入力しても大丈夫です。

 

シンプルなメールを送るスクリプト

では、シンプルなプレーンテキストメールを送信するスクリプトを掲載します。以下のようになります。

 

function sentRssToMailPlain(){
  var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RSSシート');
  var recipient = 'メールアドレス'; //送信先メールアドレス
  
  //昨日の日付を取得
  var date = new Date();
  date.setDate(date.getDate() - 1);
  var yesterday = Utilities.formatDate(date, 'Asia/Tokyo', 'YYYY-MM-dd');
  
  var lastRow = sh.getLastRow();
  
  //スプレッドシートにあるRSSフィードの数だけループを回す
  for(var i=2;i<lastRow+1;i++){
    var canSendMail = false;
    var subject = sh.getRange(i, 1).getValue(); //メールの題名
    var feedURL = sh.getRange(i, 2).getValue(); //RSSフィードのURL
    var body = "" //メール本文を初期化
    
    //RSSフィードからitems(記事)を取得
    var res = UrlFetchApp.fetch(feedURL);
    var xml = XmlService.parse(res.getContentText());
    var items = xml.getRootElement().getChildren('channel')[0].getChildren('item');
    
    //itemの数だけループ
    for(var j=0; j<items.length; j++){
      //発行日を取得する
      var pubDate = items[j].getChild('pubDate').getText();
      pubDate = Utilities.formatDate(new Date(pubDate), 'Asia/Tokyo', 'YYYY-MM-dd');
      
      //取得したitemのうち発行日が昨日のitemのみをbodyに追加
      if(yesterday == pubDate){
        canSendMail = true;
        var title = items[j].getChild('title').getText();
        var des = items[j].getChild('description').getText();
        var url = items[j].getChild('link').getText();
        body += title + '\n';
        body += des + '\n';
        body += url + '\n';
        body += '\n';
      }
    }
    
    //昨日更新の記事がある場合のみメールを送信
    if(canSendMail === true){
      MailApp.sendEmail(recipient, subject, body);
    }
  }
}

 

これで送信されたメールは以下のような感じ。

 

 

コードもシンプルで、かつプレーンテキストメールなので、少し読みづらいですよね。これをHTMLメールで送信してみます。

 

HTMLメールを送るスクリプト

HTMLメールを送るスクリプトは以下のような感じです。

function sentRssToMailHTML(){
  var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RSSシート');
  var recipient = 'メールアドレス'; //送信先メールアドレス
  
  //昨日の日付を取得
  var date = new Date();
  date.setDate(date.getDate() - 1);
  var yesterday = Utilities.formatDate(date, 'Asia/Tokyo', 'YYYY-MM-dd');
  
  var lastRow = sh.getLastRow();
  
  //スプレッドシートにあるRSSフィードの数だけループを回す
  for(var i=2;i<lastRow+1;i++){
    var canSendMail = false;
    var subject = sh.getRange(i, 1).getValue(); //メールの題名
    var feedURL = sh.getRange(i, 2).getValue(); //RSSフィードのURL
    var body = "<div style='width:100%;max-width:650px'>"; //メールの本文
    body += "<table'>";
    body += '<tr><td></td><td><h2 style="font-weight:normal;margin:0px;">' + subject + '</h2>' + yesterday + '</td><td></td><tr>';
    
    //RSSフィードからitemsを取得
    var res = UrlFetchApp.fetch(feedURL);
    var xml = XmlService.parse(res.getContentText());
    var items = xml.getRootElement().getChildren('channel')[0].getChildren('item');
    
    //itemの数だけループ
    for(var j=0; j<items.length; j++){
      //発行日を取得する
      var pubDate = items[j].getChild('pubDate').getText();
      pubDate = Utilities.formatDate(new Date(pubDate), 'Asia/Tokyo', 'YYYY-MM-dd');
      
      //取得したitemのうち発行日が昨日のitemのみをbodyに追加
      if(yesterday == pubDate){
        canSendMail = true;
        var title = items[j].getChild('title').getText();
        var des = "";
        var des = items[j].getChild('description').getText();
        var url = items[j].getChild('link').getText();
        body += '<tr>';
        body += '<td style="padding-left:18px"></td>';
        body += '<td style="padding:18px 0px 12px 0px;vertical-align:top;border-top: ridge 1px">';
        body += '<h3 style="margin:0px; font-weight:normal"><a style="style="color:#427fed;display:inline;text-decoration:none;font-size:16px;line-height:20px;" href="' + url + '">' + title + '</a></h3>';
        body += des + '\n';
        body += '</td>';
        body += '<td style="padding-right:18px"></td>';
        body += '</tr>';
      }
    }
    body += "</table></div>";
    
    //昨日更新の記事がある場合のみメールを送信
    if(canSendMail === true){
      MailApp.sendEmail(recipient, subject, body, {htmlBody:body});
    }
  }
}

HTMLタグやCSSなどが入力されていたりして、少し読みづらいですが、やっていることは共通しています。これで送信されるメールは以下の通りです。

 

 

私はGoogleAlertが好きなので、それに少し似せてみました。記事のタイトルに、URLを埋め込んでいます。また、タイトルのフォントを大きくしたり、サイト名や日付も入れてみました。

コードもかなり読みにくくなってしまいました… どなたかきれいに書き直してくださらないでしょうか…

 

トリガーを設定する

スクリプトが書けたら、これにトリガーを設定します。昨日発行分を取得したいので、朝ごろに起動するようにトリガーを設定しましょう。

これで完成です。

 

注意点

ちなみに、このスクリプトでは、itemにdescriptionの設定されていないRSSリンクの場合、エラーがでてしまいます。それを改善したい場合は、以下をご覧ください。

 

機能を追加・改善したい方へ

更新がある度にメールがほしい!

更新がある度にメールがほしいという方もいらっしゃるでしょう。その場合、スプレッドシートの特定のセルに、以前に情報を取得した日時を記録しておき、それとスクリプト実施時の日付とを比較し、以前より後に発行された記事であればそれを取得する、という処理を記述すれば良いです。そしてスクリプトを実施する度に情報を取得した日時を更新する。またトリガーも、頻度を多く設定しておけば問題ないでしょう。ただし、GASを用いてメールを送信する場合は、1日に送ることのできるメール数に限りがありますので、注意してください。時間の比較などは、以下の記事を参考にしてください。

GAS版Moment.jsライブラリで超簡単に日時の比較をする方法
Google Apps Scriptで日付&時刻の便利ライブラリMoment.jsを使う方法についてお伝えしています。今回はisSame、isBefore、isAfterメソッドで日時の比較をする方法です。

 

YahooニュースのRSSフィードも取得したい!

注意点の箇所に、RSSフィードにdescriptionがないとエラーが起きる旨を紹介しました。RSSフィードを取得できるサイトで、descriptionのない有名なサイトはyahooニュース関連のサイトです。これらのサイトには、descriptionがありません。なので、descriptionがフィード内にない場合は、それからテキストを取得するという箇所をスキップする必要があります。そのためには、処理の最初に、item内を調べ、それにdescriptionが含まれるかを調べる処理を挿入する必要があります。そして、その有無によってdescriptionからテキストを取得するという処理をスキップすれば良いでしょう。参考として、RSSの構造を説明した以下のサイトを挙げておきます。

RSS 2.0 のフォーマット|RSS|Web関連特集|PHP & JavaScript Room
RSSの受信・配信方法、 HTML文法チェックやPageRank表示など無料で使えるSEOツール、 アクセス解析で分かることなどSEO対策関連、 Webページ作成に役立つフリーソフトやオンラインツール、 サイトをグレードアップさせるブログパーツの紹介、 IT用語やIPアドレスの調べ方など、知っておくといい...

 

終わりに

以上です。GASでXMLを扱ってみましたが、以外と簡単に実装できました。この分だと、Webスクレイピングも簡単に実装できそうです。GAS恐るべし。