この記事では、楽天市場の商品が指定した値段以下になったらLINEで通知を送る方法を解説します。
以下大まかな流れです。
- 予めスプレッドシートに通知してほしい商品URLと値段を書き込む
- Google Apps Scriptで1.のシートをもとに現在の値段を取得
- 1で設定した値段以下ならLINEで通知する
- Google Apps Scriptを定期的に実行する設定を行う
最終的なコードだけを見たい人は、こちらへ。
スプレッドシートの値を読み込む
スプレッドシートの準備
商品ページのURL、希望価格などを書き込むためのスプレッドシートを準備します。
Google driveで右クリックで、「Google スプレッドシート」をクリックして、スプレッドシートを新規作成します。
とりあえず、スプレッドシートに書き込む内容は「商品ページURL」「希望価格」「商品名」(自身が識別できる名前)「備考」とします。1行目はそれぞれの列の値を識別する、ヘッダーとし、2行目から実際に必要になるデータとしています。
私は、今溶接に興味があるので、溶接機と、遮光面の情報を書き込みました。以上でスプレッドシートの準備は終わりです。
Google Apps scriptの準備
スクレイピングするためのコードを書く準備をします。
Google driveで右クリックで、その他 > Google Apps Scriptをクリックします。
もし、「共有フォルダ内に作成しますか」が表示されたら、問題なければ「作成して共有」をクリックします。問題がある方は、共有フォルダ外に作成してください。
最後に、「スクリプトを作成」をクリックし、コードを書くためのファイルを作成します。
これで以下のような画面が表示されれば、スクリプトが作成できました。「無題のプロジェクト」のところは適宜好きな名前に変更してください。私は「楽天価格通知APP」としました。
値を読み込むコードを書く
ここでは、スプレッドシートにあらかじめ書き込んだURLなどの情報をGAS(Google Apps Script)で読み込みます。
11行目の「スプレッドシートID」のところには、スプレッドシートを表示したときのURL、「https https://docs.google.com/spreadsheets/d/{スプレッドシートID}/edit」の{スプレッドシートID}の部分で置換してください。
スプレッドシートからデータを読み込む関数はreadFromSpreadsheetに実装しています。11~14行目で、11行目で指定したスプレッドシートから値が書き込まれている範囲を取得し、valuesという変数に格納しています。
17行目でlet i = 1として、ヘッダー行をスキップしています。17~25行目でvaluesから1行づつ取り出し、オブジェクトを作成し、dataというリストに格納しています。例えば、スプレッドシートに2行データがあると、dataの要素は2つになります。
最後に27行目でdataを呼び出し元に返しています。
function main() {
let data = readFromSpreadsheet();
console.log(data);
}
/**
* スプレッドシートからURL,希望価格などを読み込む
* @returns {Array.<Object>} data
*/
function readFromSpreadsheet() {
const spreadSheetId = "スプレッドシートID";
let spreadsheet = SpreadsheetApp.openById(spreadSheetId);
let range = spreadsheet.getDataRange();
let values = range.getValues();
let data = [];
for (let i = 1; i < values.length; ++i) {
let row = values[i];
data.push({
url: row[0],
price: Number(row[1]),
itemName: row[2],
note: row[3]
})
}
return data;
}
説明だけではよくわからないと思うので、ここまでのコードを実行してみます。
「実行する関数」にmainを選択し、「実行」ボタンをクリックします。
もし「承認が必要です」のダイアログが表示されたら、以下のように選択して実行します。
- 「権限を確認」をクリック
- アカウントを選択
- 「詳細」クリック
- 「無題のプロジェクト(安全ではないページに)移動」クリック
- 「許可」クリック
実行され、画面下部に以下のように出力されていれば成功です。出力される内容はスプレッドシートに書き込んでいる内容ですので、キャプチャと全く同じになるとは限らないのでご注意を。
価格をスクレイピング
いよいよ、前節で取得したURL情報から楽天市場の商品の価格をスクレイピングします。
main関数にコードを追記し、新たに、getRakutenPriceという関数を追加しています。
getRakutenPrice関数は楽天市場の商品URLを渡すと、その商品の価格を返す関数です。
40~41行目で、URL先ページのhtmlを取得しています。44~50行目で、そのhtmlから商品の価格を正規表現を使って、抜き出しています。価格を取得できた場合は文字列から数値に変換してから、呼び出し元に返し、価格を取得できなかった場合は、nullを返しています。
function main() {
let data = readFromSpreadsheet();
for (let i = 0; i < data.length; ++i) {
let price = getRakutenPrice(data[i].url);
console.log(price);
}
}
/**
* スプレッドシートからURL,希望価格を読み込む
* @returns {Array.<Object>} data
*/
function readFromSpreadsheet() {
const spreadsheetId = "スプレッドシートID";
let spreadsheet = SpreadsheetApp.openById(spreadsheetId);
let range = spreadsheet.getDataRange();
let values = range.getValues();
let data = [];
for (let i = 1; i < values.length; ++i) {
let row = values[i];
data.push({
url: row[0],
price: Number(row[1]),
itemName: row[2],
note: row[3]
})
}
return data;
}
/**
* 楽天商品ページURLから価格取得
* @type {string} url
* @returns {number|null} 取得した価格
*/
function getRakutenPrice(url) {
// 楽天商品ページ取得
let response = UrlFetchApp.fetch(url);
let html = response.getContentText();
// 楽天商品ページから価格を抜き出す
let regex = /data-price="(\d+)"/;
let match = regex.exec(html);
if (match && match.length > 1) {
let priceValue = match[1];
return Number(priceValue);
}
return null;
}
main関数では、スプレッドシートから読み込んだ商品データ数だけ、getRakutenPrice関数を呼び出し、それぞれの価格を取得しています。
実行し、以下のように表示されていれば成功です。
LINEで通知
トークン発行
LINEで通知を送るために必要になるトークンを発行します。詳しくはこちらの記事で解説していますので、詳細はこちらを参照してください。
LINE Notifyにログインし、マイページから「トークンを発行する」をクリックします。トークン名を適当に入力し、通知先のトークルームを選択します。私は以下のようにしました。
「発行する」ボタンをクリックすると、発行されがトークンが表示されます。トークンは一度しか表示されないので、どこかにコピーして後で参照できるようにしておきます。これでトークンの発行は終わりです。
通知するコード
main関数にコードを追記し、69行目以降にsendLineMsgという、LINEでメッセージを送る関数を追加しています。
sendLineMsgでは、メッセージを引数として受け取り、それをLINEで通知するコードを書いています。送信するメッセージと、アクセストークンを渡してLINEのAPIを呼び出すことで、メッセージを送信しています。
main関数では、現在の価格が希望価格以下の場合に、「商品名」「現在価格」「希望価格」「商品URL」を含めたメッセージを作成し、sendLineMsg関数を呼び出すことで、LINEにメッセージを送信しています。
このメッセージは必要に応じてカスタマイズしていただけたらと思います。
function main() {
let data = readFromSpreadsheet();
for (let i = 0; i < data.length; ++i) {
// 現在の価格を取得
let currentPrice = getRakutenPrice(data[i].url);
if (!currentPrice)
continue;
// 現在の価格が希望価格以下ならLINEで通知
if (currentPrice <= data[i].price) {
let msg = '\n今が買い時!!';
msg += '\n' + `商品名:${data[i].itemName}`;
msg += '\n' + `現在価格:${currentPrice}円`;
msg += '\n' + `希望価格:${data[i].price}円`;
msg += '\n' + `商品URL:${data[i].url}`;
sendLineMsg(msg);
}
}
}
/**
* スプレッドシートからURL,希望価格を読み込む
* @returns {Array.<Object>} data
*/
function readFromSpreadsheet() {
const spreadsheetId = "スプレッドシートID";
let spreadsheet = SpreadsheetApp.openById(spreadsheetId);
let range = spreadsheet.getDataRange();
let values = range.getValues();
let data = [];
for (let i = 1; i < values.length; ++i) {
let row = values[i];
data.push({
url: row[0],
price: Number(row[1]),
itemName: row[2],
note: row[3]
})
}
return data;
}
/**
* 楽天商品ページURLから価格取得
* @type {string} url
* @returns {number|null} 取得した価格
*/
function getRakutenPrice(url) {
// 楽天商品ページ取得
let response = UrlFetchApp.fetch(url);
let html = response.getContentText();
// 楽天商品ページから価格を抜き出す
let regex = /data-price="(\d+)"/;
let match = regex.exec(html);
if (match && match.length > 1) {
let priceValue = match[1];
return Number(priceValue);
}
return null;
}
/**
* msgをlineで送信する
*/
function sendLineMsg(msg) {
let accessToken = "前節で発行したトークンで置換";
let options = {
method: "post",
payload: `message=${msg}`,
headers: {
Authorization: `Bearer ${accessToken}`
}
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}
では実行してみます。70行目は前節で取得したアクセストークンで置換してください。LINEで通知が来るように、スプレッドシートの希望価格を現在の価格より高くしてから実行します。
LINEにこのようなメッセージが届いて入れば成功です!!
Google Apps Scriptを定期実行する設定をする
最後にGASを1日1回自動実行する設定を行います。
左の時計ボタンをクリックして、右下の「トリガーを追加」をクリックします。
以下のように設定して、「保存」ボタンをクリックします。これで1日1回自動実行する設定ができました。これですべて完了です。お疲れさまでした!