この記事でできるようになること
GAS(Google Apps Script)を使って特定のWebサイトをスクレイピングして新規投稿があった時、LINEに通知として日付、投稿名とURLが来るようにできる
前提
- LINEアカウントを持っている
- Googleアカウントを持っている
準備
Googleドライブを開き、新規 ー その他 ー Google Apps Script をクリック

Google Apps Scriptが開かれます

実装手順
[ テスト ] ログ出力
▷実行 をクリックすることで下記の実行ログにログが出力されます。

URLを設定
スクレイピングするページを開きURLをコピーする
今回はこのエンジニアパパブログにします

htmlデータを取得
let url = “https://engineer-papa.com/”;
// URLに対しフェッチを行ってHTMLデータを取得する
let html = UrlFetchApp.fetch(url).getContentText();
これでHTMLデータを取得できます。

権限を確認 をクリック

ご自身のGoogleアカウント を選択してください

詳細 をクリック

エンジニアパパ投稿通知(安全ではないページ)に移動 をクリック

許可 をクリック

HTMLデータが実行ログに出力されます

最新投稿の日付を取得
スクレイピングするためのライブラリ追加
ライブラリ をクリックし下記のスクリプトIDを入力し 検索 をクリック
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

Parserがヒットされたことを確認し、追加 をクリック

スクレイピングするページを開き、F12などをクリックしデベロッパーツール(開発者モード)を開き、Elementsをクリックし、その左側にある 矢印マーク をクリック
左上の投稿が最新投稿のため、そのタイトルをクリックすると右側の黒いところから日付を探しその前後の文字列をコピー

ソースに下記を追加し、▷実行 をクリック
// 最新投稿の日付を取得 (yyyy-mm-dd)
let noticeDates = Parser.data(html)
.from(“datetime=\””)
.to(“\”>”)
.iterate();

権限を確認 をクリック

許可 をクリック

実行ログに先ほど取得した日付の前後の文字列に該当する日付が出力されます。

下記を追記する
noticeDates に [0] を付け足すことで最初の文字列を取得できます。
let newNoticeDate = noticeDates[0];
Logger.log(newNoticeDate);

最新投稿のタイトルを取得
日付の時と同じようにデベロッパーツールでタイトルの前後の文字列をコピー

下記をソースに追記し、実行すると実行ログに新規投稿のタイトルが出力されます。
// 最新投稿のタイトルを取得
let noticeStrings = Parser.data(html)
.from(“<h2>”)
.to(“</h2>”)
.iterate();
let newString = noticeStrings[0]
Logger.log(newString);

最新投稿のタイトルを取得
日付とタイトルの時、同様にデベロッパーツールで最新投稿詳細のリンクの前後の文字列をコピー
前: <a class=\”cardtype__link\” href=\”

下記をソースに追記し、実行すると実行ログに新規投稿詳細のリンクURLが出力されます。
// 最新投稿の記事URLを取得
let detailsUrls = Parser.data(html)
.from(“<a class=\”cardtype__link\” href=\””)
.to(“\””)
.iterate();
let newDetailsUrl = detailsUrls[0]
Logger.log(newDetailsUrl);

LINE通知用に整形
下記のように書き、見やすいようにする
// LINEに送信するために整形
sendMessage = “\n” + newNoticeDate + “\n” + “\n” + newString + “\n” + newDetailsUrl;
Logger.log(sendMessage);

LINE Notifyの設定
下記にアクセスし、メールアドレス、パスワードを入力し、ログインする
https://access.line.me/dialog/oauth/weblogin?response_type=code&client_id=1476232700&redirect_uri=https%3A%2F%2Fnotify-bot.line.me%2Flogin%2Fcallback&state=KftMrM6xpgZSZTDca1UseM

右上の名前の右にある ▽ボタン をクリック

マイページ をクリック

スクロールし、トークンを発行する をクリック

トークン名を入力し、通知するトークルームを選択してください。
今回は下記のように設定し、 発行する をクリック
トークン名 :エンジニアパパブログ通知
トークルーム:1:1でLINE Notifyから通知を受け取る

トークンが発行されます
コピー をクリックし、トークンをコピー

LINE Notifyの連携トークンをGASに設定しスクレイピング情報をLINEに通知
ソースに下記を追記し、実行をクリック
先ほど整形した文字列が LINE に通知されるはずです
通知されればほとんど完了です。
const token = “[ コピーしたトークン ]”;
var message = sendMessage;
var options = {
“method” : “post”,
“headers”: { “Authorization”: “Bearer ” + token },
“payload” : { “message”: message }
};
UrlFetchApp.fetch(“https://notify-api.line.me/api/notify”, options);

新規投稿があった場合のみ通知されるように設定
現在のままだと実行するたびにLINEに通知が来てしまいます。
前回取得した日付と今回取得した日付を比較し、違った時のみ通知するようにします。
ソースの最新投稿日付を取得した次の行に下記を追記する
// 最新投稿の日付を取得 (yyyy-mm-dd)
let noticeDates = Parser.data(html)
.from(“datetime=\””)
.to(“\”>”)
.iterate();
let newNoticeDate = noticeDates[0];
// プロパティに保存した前回の日付を取得
var lastDate = PropertiesService.getScriptProperties().getProperty(“NEW_NOTICE_DATE_ENGINEER_PAPA”);
// 前回日付と今回の最新日付を比較
if (lastDate !== newNoticeDate) {
取得した最新日付と NEW_NOTICE_DATE_ENGINEER_PAPA にに保存されている日付を比較する
※次の項目でNEW_NOTICE_DATE_ENGINEER_PAPA に日付を保存します

LINEに通知した次の行に下記を追記する
UrlFetchApp.fetch(“https://notify-api.line.me/api/notify”, options);
Logger.log(sendMessage);
// 取得した最新日付をプロパティに保存
PropertiesService.getScriptProperties().setProperty(‘NEW_NOTICE_DATE_ENGINEER_PAPA’, newNoticeDate);
}
NEW_NOTICE_DATE_ENGINEER_PAPA に最新日付を保存する

トリガー設定
左のサイドバーの 時計マーク をクリックし、 トリガーを追加 をクリック

時間ベースのタイマー をクリックし、分ベースのタイマー にする

時間の間隔を選択(分) を 5分おき を選択し、保存 をクリック

設定したトリガーが追加されたことを確認

これで
上記で実装した処理を5分ごとに実行するようになりました。
これで前回の通知した投稿タイトルと比較して変わっていれば通知するようになりました。
実際に作ったソース
function myFunction() {
let url = “https://engineer-papa.com/”;
// URLに対しフェッチを行ってHTMLデータを取得する
let html = UrlFetchApp.fetch(url).getContentText();
// 最新投稿の日付を取得 (yyyy-mm-dd)
let noticeDates = Parser.data(html)
.from(“datetime=\””)
.to(“\”>”)
.iterate();
let newNoticeDate = noticeDates[0];
// プロパティに保存した前回の日付を取得
var lastDate = PropertiesService.getScriptProperties().getProperty(“NEW_NOTICE_DATE_ENGINEER_PAPA”);
// 前回日付と今回の最新日付を比較
if (lastDate !== newNoticeDate) {
// 最新投稿のタイトルを取得
let noticeStrings = Parser.data(html)
.from(“<h2>”)
.to(“</h2>”)
.iterate();
let newString = noticeStrings[0]
// 最新投稿の記事URLを取得
let detailsUrls = Parser.data(html)
.from(“<a class=\”cardtype__link\” href=\””)
.to(“\””)
.iterate();
let newDetailsUrl = detailsUrls[0]
// LINEに送信するために整形
sendMessage = “\n” + newNoticeDate + “\n” + “\n” + newString + “\n” + newDetailsUrl;
consttoken = “[ コピーしたトークン ]”;
var message = sendMessage;
var options = {
“method” : “post”,
“headers”: { “Authorization”: “Bearer ” + token },
“payload” : { “message”: message }
};
UrlFetchApp.fetch(“https://notify-api.line.me/api/notify”, options);
Logger.log(sendMessage);
// 取得した最新日付をプロパティに保存
PropertiesService.getScriptProperties().setProperty(‘NEW_NOTICE_DATE_ENGINEER_PAPA’, newNoticeDate);
}
}
注意
この実装は完全な新規投稿通知ではないです。
5分以内に2つ投稿があった場合
2つ目の投稿のみLINE通知が届きます。
また、新規投稿があった場合、即座にLINE通知が届くわけではないです。
スクレイピングは禁止しているWEBサイトもあります。
また、著作権侵害になる可能性もありますので十分注意して実装してください。
以上、最後までご覧いただきありがとうございます。