株式会社WR

株式会社WR

WEB TOTAL CONSULTING

GASからLINE Notifyで通知を送る——スクレイピングアラートの実装
ブログ一覧へ
技術ブログ

GASからLINE Notifyで通知を送る——スクレイピングアラートの実装

GASとLINE Notify APIを組み合わせると、スマートフォンのLINEにリアルタイム通知を送れます。価格アラート・在庫復活通知・日報送信などに活用できます。

LINE Notifyとは——手軽なプッシュ通知

LINE Notifyは、LINE公式が提供するAPIサービスで、トークンを使ってLINEのトークルームに通知を送ることができます。Slackと異なりスマートフォンへのプッシュ通知が確実に届くため、「すぐに気づきたい」アラートに最適です。


LINE Notifyの設定

  1. LINE Notify にLINEアカウントでログイン
  2. 「マイページ」→「トークンを発行する」
  3. トークン名を入力し、通知先トークルームを選択
  4. トークンをコピー(再表示されないので注意)
取得できるもの: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(40文字の文字列)

GASからLINE Notifyに送る

const LINE_NOTIFY_TOKEN = PropertiesService.getScriptProperties()
                              .getProperty('LINE_NOTIFY_TOKEN');

/**
 * LINEに通知を送る
 * @param {string} message - 通知メッセージ
 * @param {object} options - 追加オプション(画像URLなど)
 */
function sendLineNotify(message, options = {}) {
    const url = 'https://notify-api.line.me/api/notify';

    const payload = { message };

    // 画像URLがある場合
    if (options.imageUrl) {
        payload.imageThumbnail = options.imageUrl;
        payload.imageFullsize  = options.imageUrl;
    }

    const params = {
        method:  'post',
        headers: { Authorization: `Bearer ${LINE_NOTIFY_TOKEN}` },
        payload: payload,
        muteHttpExceptions: true,
    };

    const response = UrlFetchApp.fetch(url, params);
    const result   = JSON.parse(response.getContentText());

    if (result.status !== 200) {
        console.error('LINE通知エラー:', result.message);
        return false;
    }
    return true;
}

// テスト送信
function testLineNotify() {
    sendLineNotify('\nテスト通知です\n' + new Date().toLocaleString('ja-JP'));
}

スクレイピングアラートの実装

/**
 * Amazonの価格をスクレイピングしてアラートを送る
 */
function checkAmazonPriceAndAlert() {
    const sheet = SpreadsheetApp.getActiveSpreadsheet()
                                 .getSheetByName('監視リスト');
    const data  = sheet.getDataRange().getValues();

    const alerts = [];

    // ヘッダー行をスキップ
    for (let i = 1; i < data.length; i++) {
        const asin        = data[i][0];
        const productName = data[i][1];
        const targetPrice = parseFloat(data[i][2]);
        const lastPrice   = parseFloat(data[i][3]) || 0;

        // Amazon Price APIから現在価格を取得(簡易版)
        const currentPrice = fetchAmazonPrice(asin);

        if (currentPrice > 0) {
            // スプレッドシートに現在価格を記録
            sheet.getRange(i + 1, 4).setValue(currentPrice);
            sheet.getRange(i + 1, 5).setValue(new Date());

            // 目標価格以下になったらアラート
            if (currentPrice <= targetPrice) {
                alerts.push({
                    name:        productName,
                    asin:        asin,
                    target:      targetPrice,
                    current:     currentPrice,
                    diff:        targetPrice - currentPrice,
                    lastPrice:   lastPrice,
                    priceChange: currentPrice - lastPrice,
                });
            }
        }
    }

    if (alerts.length > 0) {
        const message = formatAlertMessage(alerts);
        sendLineNotify(message);
    }
}

function formatAlertMessage(alerts) {
    const lines = ['\n🔔 価格アラート\n'];

    alerts.forEach(a => {
        lines.push(`━━━━━━━━━━`);
        lines.push(`📦 ${a.name.substring(0, 20)}`);
        lines.push(`💰 ¥${a.current.toLocaleString()} (目標: ¥${a.target.toLocaleString()})`);

        if (a.priceChange < 0) {
            lines.push(`📉 前回比: ▼¥${Math.abs(a.priceChange).toLocaleString()}`);
        }

        lines.push(`🔗 https://www.amazon.co.jp/dp/${a.asin}`);
    });

    return lines.join('\n');
}

スクレイピングエラーのアラート

/**
 * エラー通知付きでスクレイピングを実行
 */
function runWithLineAlert(taskName, fn) {
    const startedAt = Date.now();

    try {
        const result = fn();
        const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1);
        console.log(`${taskName} 完了: ${elapsed}秒`);
        return result;
    } catch (error) {
        const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1);
        const message = [
            '',
            '⚠️ GASエラー発生',
            `タスク: ${taskName}`,
            `エラー: ${error.message}`,
            `経過: ${elapsed}秒`,
            `時刻: ${new Date().toLocaleString('ja-JP')}`,
        ].join('\n');

        sendLineNotify(message);
        throw error; // 再スロー
    }
}

// 使い方
function main() {
    runWithLineAlert('価格チェック', checkAmazonPriceAndAlert);
    runWithLineAlert('在庫確認', checkInventory);
}

定期実行スケジュール

/**
 * トリガー設定
 */
function setupTriggers() {
    // 既存削除
    ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t));

    // 平日9時・12時・18時に価格チェック
    ['9', '12', '18'].forEach(hour => {
        ScriptApp.newTrigger('main')
            .timeBased()
            .atHour(parseInt(hour))
            .everyDays(1)
            .inTimezone('Asia/Tokyo')
            .create();
    });
}

Slack vs LINE Notify の使い分け

観点 Slack LINE Notify
PC通知 良好 普通
スマホ通知 良好 確実(LINEプッシュ)
チャンネル管理 柔軟 シンプル
コスト 無料プランあり 完全無料
向いている用途 チーム内共有・複数チャンネル 個人アラート・緊急通知

弊社ではSlackを日常のチーム通知に、LINE Notifyを「すぐ気づきたい」緊急アラートに使い分けています。


まとめ

GAS + LINE Notifyの組み合わせは、無料・サーバーレスでスマートフォンへのプッシュ通知を実現できるシンプルで強力な構成です。価格アラート・エラー通知・日次サマリーなど様々な用途に応用できます。

業務自動化・通知システムの開発についてはお気軽にご相談ください。

Category 技術ブログ

Related Posts

関連記事

開発・技術のご相談はお気軽に

お見積りは無料です。まずはお気軽にご相談ください。

お問い合わせ →