Google Apps ScriptでRSSリーダーを作る【GAS】

Google Sitesでは用意されてる標準のウェブパーツ以外にも、Google Apps Scriptで作成された独自のパーツも簡単に作る事が可能です。特に企業のポータルサイトとして需要が高いのが「情報を自動で集めて表示してくれるウェブパーツ」です。ただ、よくあるパーツだと結局、自分の好みに合わないだとか、痒いところに手がとどかないなどで、満足度が低いことがままあります。

今回はRSS2.0とAtom形式の2種類をスプレッドシートに登録するだけで、簡単に複数チャンネルのRSSを見られるパーツを作ってみたいと思います。

今回使用するスプレッドシート

サンプルプログラム

今回使用するスプレッドシートサンプルはとてもシンプルです。dataというシートが1枚あるだけです。利用する場合には、必ず「ファイル」⇒「コピーを作成」してから利用してください。また、メニューより「セットアップ」⇒「スタート」を実行して、セットアップを完了しないと使えません。

改のほうは、後半のVuetifyで作り直した版で、現在このサイトのRSSリーダーパーツとして使っています。

図:タブで表示切り替えるタイプのパーツです

注意事項

  • 開いたら、メニューに「セットアップ」という項目があるので、必ず「スタート」を実行しましょう。これは、コピーしたら必ず実行します。スプレッドシートのシートIDをスクリプトプロパティに格納するコードが入っています。
  • 今回のパーツは、ウェブアプリケーションですので、コピーしたら必ず、スクリプトエディタに入って、「公開」⇒「ウェブアプリケーションとして導入」を実行し、公開しましょう。
  • RSS2.0とAtomに対応させていますが、世の中にあるRSSの中には変な形式のRSSフィードがあったりするので、全てを読み込めるわけではありません。コードで追加対応が必要です。
  • 幅には限界があるので登録するフィードは10個ほどにしておきましょう。タイトルタブが見切れる事があります。

RSSフィード登録の仕方

  1. タイトルは自由に。これが今回のRSSリーダーのタブに表示されます。
  2. URLにはRSSフィードやGoogle NewsのAtom出力URLなどを入れておきます。
  3. RSSにはRSSのタイプを登録。このセクションでコード内で条件分岐しています。

図:スプレッドシートに記述するだけの簡単仕様

RSSリーダーを作る

RSSリーダー生成

アプリのUI部分

今回はスマートフォン用のインターフェースを使って実装しています(いつもはjQueryを使う所ですが)。自分が好んで使ってるライブラリである「Framework7」を使っています。iOS用のCSSの他にもAndroid用のCSSも用意されている便利なものです。タブをクリックすると、ページの一番上にまで戻るように「scrollTop」の関数を生成時にイベントとして追加しているのがポイントです(これがないと、タブ切り替わっても、同じ位置から見ることになって挙動としてはダサいです。

アプリのUI部分はindex.htmlに記述します。

  • 冒頭のgoogle.script.withSuccessHandler(onSuccess).tabmaster()にてGAS側から生成したUI用データを取得し、idがtabmanとtablistの2つに反映させています。
  • HTML部分はFramework7独自のUIフレームワークで、AngularJSでも見るようなちょっと変わったHTMLタグになっています。このあたりは、公式ドキュメントをご覧下さい。
  • framework7本体のjsファイルは必ずHTMLの後半に記述します。
  • framework7の初期化設定用のjsファイルも同様に後半に記述します。

初期化設定用のrss.jsファイルには初期化の為のいくつかの設定を記述しています。jQueryと被らないようにDOMセレクタのワードは$7という名称で選択するように指定してあります。rss.jsの詳細の初期設定コードは以下の通りです。

アプリのUI生成部分

UI用の各種HTMLデータはGoogle Apps Script側で生成しています。スプレッドシートのデータを取得し、RSSタイプに応じて分解、生成したHTMLをまとめて、index.html側へ返しています。GAS側メイン関数はgoogle.script.withSuccessHandler(onSuccess).tabmaster()で呼び出されて、表示時に自動実行しています。

まずはアプリのUIであるindex.htmlを表示してあげます。

  • 今回は外部サイト磔に対応させる為のオプションとして、.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)を指定しています。
  • スマフォ表示用のオプションとして、.addMetaTag("viewport", "initial-scale=1.0")を指定しています。

メインとなる関数はtabmaster()で記述してあげてます。

タブ部分をtabmanとし、RSSの中身をtablistとしてそれぞれ別々の配列に生成し、まとめてあげています。Framework7を使ってる為、生成するHTMLはやや特殊なものになっています。tabをクリック時にscrolltop関数で上に戻るように予め、onClick属性を付け加えておいてあげています。

RSS2.0対応コード

古いタイプのRSSフィードで使われてるのが、RSS2.0でindex.rdfなどというファイルの形で生成されてる事が多いです。未だに絶滅する事なく日本のサイトでは使われているのを見かけます。このコードの中には変な形式のものも含まれていたりするので、そういったものはコードで追加対応が必要です。

原始的で扱いにくいので、xml2jsonJSONに変換するコードを噛ませています。

Atom対応コード

最近のRSSフィードはほぼこのAtom形式で配信されていますので、こちらのコードで殆どが対応可能です。Google Newsの検索フィードもAtomで配信されていますが、値の取り方が大幅に変更になっていますので分岐させました。また、Atomはサイトによって方言がたくさんあるため、個別にカスタマイズが必要なケースが非常に多いです。

このサイトでも利用している最新情報はこのスクリプトを利用しています。RSSによって差が大きいため、上記のプログラム内で取得するURLの位置に関しては、第二引数の値で分岐させていたりします。

Google Workspace Update Blog対応コード

feedburnerの仕様変更で、名前空間の指定でorigLinkの値を取る必要があるため、nsfeedburnerを追加しgetChildで取るように変更を加えています。基本、RSSの構造を解析して名前空間の指定で子要素は取れるようになりますが、面倒な場合は無理してXML解析せずにXML2JSONでパースしたほうが楽になれます。

※現在Google Developer BlogのFeedと同じ形式になったので、-2ではなく-4のオプションを使うように変更しています。

Google News対応コード

2018/12/18:Google NewsからのRSSがうまく取得できなくなってたのに気がついたので修正。シンプルになったものの、他のAtom形式から少し変更が加わっているのと、Google Newsに渡すURLパラメータが変更されていたので、スクリプトを分岐させました。

表示サンプル

今回は、Google Apps Scriptに特別なオプションを追加して、このWordPressのサイトにも貼り付けてみました。貼り付けはウェブアプリのURLをiFrameタグで囲って貼り付けてるだけです。GASの色々な手法とオプションはいずれまとめて1個のエントリーで紹介してみたいと思います。

図:このサイトにも貼り付けてみた

Vuetifyで作成しタイトルを自動翻訳

前述のRSSリーダーを更に発展して以下の機能をつけたものをRSSリーダー改として作成しました。変更点は

  • UIフレームワークをFramework7からVuetifyに交換
  • トリガーを使い、6時間毎RSSデータを取得したものを表示するように変更(アクセスする毎だと重い為)
  • 英語のサイトのタイトルは取得時に日本語翻訳して記録するように変更

表示サンプルはこちらのページに掲載しています。

レスポンスが良くなったのと、Vuetify + Vue.jsによるコードの最適化がメンテナンス性向上につながっています。アクションの地球儀アイコンをクリックで、対象のサイトを開くようにしています。できれば時刻も記録して自動でソートも付け加えたいところ。

図:スピードアップ且つ利便性向上しました

Google NewsのAtomフィードについて

通常のウェブサイトでは、標準でRSSフィードへのURLなどが公開されています。しかし、一番利便性の高い「Google News」のフィードは、日本版Google Newsでは配信されていません(米国版は配信されています)。Google Newsのフィードは検索ワードに応じたニュースヘッドラインと要約を取得出来るので、物凄く便利なのに・・・

しかし、米国版のGoogle Newsでも日本語の検索結果は出力出来るので、それを利用しましょう。作り方は以下の通り。

  • https://news.google.com/_/atom/search?ie=UTF-8&q=というURLがベースになります。
  • q=につづけて、「検索ワード」を入れます。
  • 但し、複数検索ワードを入れる場合にはスペース区切りですが、URLエンコードする必要があります。スペースは「%20」になりますので、「自動車 電気」というワードならば「q=自動車%20電気」という文字列になります。
  • 続けて、「&num=100」と入力すると、100件出力というオプションになります(最大100件しかAtom出力できないようです)

特定業界のニュースネタや情報を収集する手段としては、地味な手法ですが非常に有効な手法です。また、RSS配信されていないようなサイトでも強引にRSSフィードを生成してくれる「Feed Creator」といったサービスを使って、RSSを準備して用いるのも有効ですね。「電気自動車」での検索結果は以下の通りとなります。

https://news.google.com/_/atom/search?ie=UTF-8&q=トヨタ&num=100&hl=ja&gl=JP&ceid=JP:ja

Google検索結果をRSSで取得する

Googleの検索結果をRSSで取得したい事があります。これらもRSS化することが可能です。以下の手順でRSSフィードを生成しましょう。

  1. Googleアラートにアクセス
  2. 検索窓にキーワードを入れる。
  3. いろいろとオプションを設定する。配信先はRSSを設定
  4. アラートを作成をクリック
  5. 作成後はRSSのアイコンがそのURLになります。

図:Googleアラート久しく使ってないなぁ・・・

より簡単なRSSフィードの一覧化

今回紹介したスクリプトは正攻法で丁寧にRSSフィードを分解して取り込んでいます。一方で、Googleスプレッドシートには非常に便利な配列で返してくれる関数の一つに「Importfeed関数」という特殊な関数があります。使い方はとても簡単で、importfeed関数の引数にシングルコーテーションでfeedのURLを入れて上げるだけ。あとは自動で分析して、シートに一覧表示してくれる。結構昔からある便利な関数で、Googleスプレッドシートでのみ使えます。

この関数を使った場合、自動で最新のフィード20件を取得してくれるので、プログラムはより簡単になります。サンプルシートにはGoogle Newsの検索結果を入れてあります。関数の書き方は以下の通り。

ちなみにこの関数にさらにオプション指定をすると細かく挙動を制御出来る。importfeed関数の引数は以下の通り。

  • 表示する列は「items」と入れる、もしくは空だと全てが表示され、「items title」と入れるとタイトルのみが表示される(AuthorやURL、Summaryなどがこれに該当)。これはそのRSSフィードの項目によるので、一度中身を見て指定すると良いでしょう。
  • タイトル行の有無はデフォルトはFalseだけど、Trueにすると、タイトル行を自動で入れてくれる
  • 件数は数値で入力。ここで100と入れると100件表示される。

図:簡単にフィードを分解してくれるスグレモノ関数

更新履歴

  • ※2018/12/18 : どうも、11/27頃にGoogle NewsのRSSフィード出力のURLおよびその内容に変更があったようで、スクリプトおよびそのURLについて修正しました。
  • ※2019/5/9:titleにタグのようなものが混じってるエントリーの場合、parsexmlに不具合が生じるので、エスケープ文字にリプレースするように変更しました。
  • ※2020/12/18 : RSS1.0を廃止しRSS2.0のみ(ただし、Teratailしか検証していないです)
  • ※2020/12/18 : GSuite Update Blogの表示がおかしかったので、namespaceを追加しfeedburnerに対応しました
  • ※2021/11/15:Google Workspace Update BlogのFeedの形式がDev Blogと同一になったので、オプションを-2から-4に変更しました。

関連リンク

Google Apps ScriptでRSSリーダーを作る【GAS】” に対して4件のコメントがあります。

  1. おと より:

    RSS1.0を廃止とのことですが、対応してほしいです。

    1. officeの杜 より:

      おと様

      旧式のRSSリーダーのサンプルファイルには、getRSS10という関数が入っており、一応残っています。

      ただ、RSS1.0は本当に初期の頃の規格故に、ふわっとした規格なので、サイトによって妙な変更や追加がされていたりするので、サイトに合わせて改造が必要なケースが多いと思います。
      サンプルファイルを使ってみて対応してみてはいかがと思います。

  2. gunzi より:

    参考にさせていただいています。
    以下ようなRSSリーダーを取得を行おうとした際に、対応できなかったのですがこちら対応する方法とかってありますでしょうか…!?
    http://www3.asahi.com/rss/national.rdf
    http://sankei.jp.msn.com/rss/news/points.xml

    1. officeの杜 より:

      2個目のURLが見えないので1つ目での方法ですが、RSS1.0ですので、RSS1.0での対応方法で出来ると思いますが、RSS1.0のフォーマットは
      きちんとした コレ という定義がされていない、かなり各社バラバラの仕様なので、出来なくはないと思いますが大変だと思います。

      ただ、RSSリーダーのページのものは、1.0を廃止してしまったので、かつてのコードは以下のエントリーに残っています。
      https://officeforest.org/wp/2019/11/28/%e6%96%b0%e3%81%97%e3%81%84google-sites%e3%81%ab%e3%83%8d%e3%82%a4%e3%83%86%e3%82%a3%e3%83%96%e3%81%aarss%e3%83%aa%e3%83%bc%e3%83%80%e3%83%bc%e3%82%92%e4%bd%9c%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b/

      コードとしては

      function getRSS10(feedURL) {
      var rssdata = [];
      var response = UrlFetchApp.fetch(feedURL);
      var xml = Xml.parse(response.getContentText(), false);
      var items = xml.getElement().getElement("channel").getElements("item");
      for(var i = 0; i < items.length; i++) { var title = items[i].getElement("title").getText(); var url = items[i].getElement("link").getText(); var dateman = items[i].getElement("pubDate").getText(); var detail = items[i].getElement("description").getText(); var text = title + ' ' + url; //itemlistを生成する var temprssdata = []; temprssdata.push(title); temprssdata.push(detail); temprssdata.push(url); temprssdata.push(dateman); //rssdataにpushする rssdata.push(temprssdata); } //値を返す return rssdata; }

      となります

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)