ブログ記事に最終更新日を出すための その2
はじめに
ブログの記事に更新日を表示しようという企画の第二部です。
この記事は後編です。
前の記事はこちらです。 kanaxx.hatenablog.jp
作ったもの
記事ページに最終更新日を差し込むスクリプトです。最近覚えたGoogle Apps Scriptとスプレッドシートを使って作りました。
1か月以内なら何日前と表示
1か月以上たっている場合は何か月前と表示
1年以上経っている場合は、何年前と表示
これだけです。
作戦会議
GASだけで最終更新日を表示するのは難しいので、二つに分割して考えます。
- sitemap_indexとsitemap.xmlから記事のURLと最終更新日を取り出すGASとスプレッドシート
- GASをウェブアプリケーション化して、記事の最終更新日を取得するJavaScript
この方法であれば、記事ページを開いたときに1回だけ外部にアクセスするだけで最終更新日がとれます。
後編では、上の2番目の作業を行います。
- 前回作成したスプレッドシートにウェブアプリケーション用の関数を追加する
- GASをウェブアプリケーションとして公開をしJavaScriptから呼び出し可能な状態にする
- はてなブログにJavaScriptを埋め込み、APIを呼び出して更新日を取り出す
3. 外部呼出しの関数を追加
Google Apps Scriptを外部から利用可能(呼び出し可能)にするためのお作法があるので、それに従って実装していきます。
簡単にいうとdoGet関数かdoPost関数を作成して、デプロイするという手順を踏みます。
Develperガイドも参考に
https://developers.google.com/apps-script/guides/web
doGetの関数を準備
今回はHTTP GETでのアクセスをするので、doGet
関数だけ作ります。doPost
は不要です。
スクリプトエディタの「ファイル」の隣にある+マークで新しいファイルを作成し、以下のコードをコピペします。ファイル名は何でもよいです。
// parameter url function doGet(e){ let url = e.parameter.url; console.log('url=%s', url); let lastmod; if(url == null || (lastmod=getLastMod(url))==null){ return ContentService.createTextOutput('null'); } let now = new Date(); let diff = now - lastmod; //msec let diffDays = Math.floor(diff/1000/60/60/24); let diffMonths = Math.floor(diffDays/30); let diffYears = Math.floor(diffDays/365); console.log('%s(msec) | %s(days), %s(month), %s(year)', diff, diffDays, diffMonths, diffYears); let fullDate = Utilities.formatDate(lastmod, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss'); let shortDate = Utilities.formatDate(lastmod, 'Asia/Tokyo', 'yyyy-MM-dd'); let data = {diffYears, diffMonths, diffDays, fullDate, shortDate, url }; let payload = JSON.stringify(data); let output = ContentService.createTextOutput(); output.setMimeType(ContentService.MimeType.JSON); output.setContent(payload); return output; } //for testing function testDoGet(){ let param = { //parameter:{url : 'https://kanaxx.hatenablog.jp/entry/typec-cable'} parameter:{url : 'https://kanaxx.hatenablog.jp/entry/hatenablog/responsive-with-cloudinary'} }; let ans = doGet(param); console.log(ans); }
スクリプトはここにも置いてあります https://github.com/kanaxx/hatenablog-omocha/blob/main/ladtmodifiedtime/doget.gs
やっていることを簡単に
- doGetを定義します。パラメータとして
url=xxx
を受け取ります。- eからURLの値を取り出し、getLastModを呼びます
- getLastModは、「データ」シートのA列からURLと一致するセルを探し、見つかったときは一つ右のセルの値をとります
- 上でとった値を日付の形式にフォーマットして返します
- 最終更新日と現在時間を比較して、日数の差、月数の差、年数の差を計算しておきます
- 計算した結果をJSON形式で戻します
4.デプロイする
doGet
を作ったら、デプロイします。
デプロイとは、作ったスクリプトをインターネット側に公開をして利用できるようにする作業のことです。日本語だと配備と呼ぶことがありますがデプロイでいきます。 スクリプトエディタで書いただけでは外部から使える状態にならないので、デプロイをします。
新規にデプロイする
一回もやったことがない人は新規にデプロイします。デプロイはスプレッドシート(ワークブック)ごとに行うので、別ブックでスクリプトを書いたらそれぞれでデプロイが必要です。
スクリプトエディタの右上にあるデプロイボタンを押します。
デプロイ種類が3つ出てきますが、初めての人は「新しいデプロイ」を押します。
新しいデプロイウィンドウが出てくるので、必要事項を入力します。
といっても特に困るものはなくて
- 1はわかりやすい説明文を入れる
- 2は自分
- 3は全員
になります。「デプロイ」ボタンを押すと完了です。
新しくデプロイをすると、そのアプリケーション用のURLが発行されます。
このURLが外部からdoGetを呼ぶためのURLです。あとで使うのでメモしておきます。
プログラムを修正したは再デプロイ
一度デプロイしたあとに問題が見つかってプログラムを修正した場合には、もう一度デプロイしないと変更は反映されません。
まず、「デプロイの管理」を押し デプロイされているアプリケーションの一覧を開きます
左上のアクティブの中から変更したいものを選び、右側の編集ボタン(鉛筆マーク)を押します。
通常は左上は1つしかないので選択に困ることはないと思います。
編集ボタンを押したら、右側が入力可能になります。一番上にある「バージョン」の選択肢から「最新バージョン」を選び、デプロイボタンを押します。
デプロイ済みの状態で新しくデプロイをすると、呼び出しのURLが新しいものが割り当てられてしまいます。古いほうが使えなくなるわけではないので、慌てず急がすもう一度デプロイしなおせば大丈夫です。
ウェブアプリケーションをテスト
デプロイが完了すると、先ほどのURLをブラウザで叩ける状態になります。試しに実行してみる場合は、このような形式で実行します。 \https://script.google.com/macros/s/xxxxxxx/exec?url=123
最終部分にurl=123の形式でパラメータを指定します。123の部分に存在するURLに変更すれば結果が取れます。
こんな感じでデータが取れます。
5.JavaScriptから呼び出す
やっと最終ステップです。
データを貯めるスプレッドシートができ、 スプレッドシートに自動でデータを持ってくる仕組みができ、 スプレッドシートのデータを外部に返す仕組みができたので、 次は取り出す部分です。
コード
JavaScript側のコードはシンプルです。GASにアクセスしてデータを取り出し、戻ってきた値を少々加工してページ内に埋め込むだけです。
CSSもセットで置いてしまっていますが、デザインCSSエリアに置くのでもいいと思います。
<script> //Change here to your own URL let lastmodURL = 'https://script.google.com/macros/s/xxx-yyy/exec'; fetch( lastmodURL + '?url=' + location.href) .then(response=>response.json()) .then(lastmod=>{ console.log(lastmod); if(lastmod !=null && $('div.entry-date').length==1){ let diffText = ''; if( lastmod.diffYears > 0 ){ diffText = ' (' + lastmod.diffYears+'年前)'; }else if( lastmod.diffMonths > 0 ){ diffText = ' (' + lastmod.diffMonths +'ヵ月前)'; }else if( lastmod.diffDays > 0) { diffText = ' (' + lastmod.diffDays +'日前)'; $('div.entry-date').after('<span class="entry-lastmod">更新日:'+lastmod.shortDate + diffText+'</span>'); } }); </script> <!-- design for lastmod --> <style> span.entry-lastmod{ margin-left:20px; font-size:80%;} </style>
簡単に説明
fetch
メソッドを使って外部URLへ接続します。
jsonデータ(変数:lastmod)が受け取れた場合は、表示する内容をifの3分岐で調整しています。
- lastmod.diffYearが1以上なら「x年前」
- lastmod.diffMonthが1以上なら「xヵ月前」
- lastmod.diffDaysが1以上なら「x日前」
最後に、<span>
タグを作成し、日付周辺に適当に押し込みます。(ここでjQuery使っちゃう弱者です)
JavaScriptを設置
今回のスクリプトは記事ページだけが反応すればよいので、記事下エリアに差し込みます。
ブログ管理画面の「デザイン設定」>「カスタマイズ」>「記事」>「記事下」のHTMLエリアに上のコードを貼り付けます。
保存すれば終わりです。
6. 動作確認
適当に記事ページを閲覧するだけです。
公開したGASが呼び出された場合には、GASの実行数のページにリアルタイムに表示されます。
無事、最終更新日が表示できました。
まとめ
Google Apps Scriptをデプロイし、別のアプリケーション(はてなブログ)から呼び出す連携を作ってみました。
GASのトリガーで自動でデータを集めデータベース化し、そのデータを検索可能な形でデプロイするのは意外と応用が効く仕組みだと思います。
とりあえず作りたかっただけなので、自己満足です。
参考にしたサイト
Develperガイド
https://developers.google.com/apps-script/guides/web
GASでJSONを返すAPIを作る
https://qiita.com/tfuruya/items/3c306ee03d1ac290bcef