GASは本来静的サイトのスクレイピングが得意ですが、APIを活用することで動的サイトにも対応できます。
▼参考サイト
https://qiita.com/kg_japan/items/f3d14ca7f86767092546
APIの準備
PhantomJsCloudにアクセスして、Sign upするとAPIキーを取得することができます
phantomjscloud.com


GASのコード
const APIKEY = ''; // PhantomJsCloudで取得するAPIキー
const DELAY_TIME = 10; // スクレイピング中の操作に対する待機時間
// PhantomJsCloudのエンドポイントを返す関数
const endpoint = apiKey => `https://PhantomJScloud.com/api/browser/v2/${apiKey}/`;
// スクレイピングの操作に関するペイロードを返す関数
const payload = (month, day, sisetu, delayTime) => ({
url: 'https://www.net.city.nagoya.jp/cgi-bin/sp05001',
renderType: 'html',
outputAsJson: true,
overseerScript: (`
// 月の選択
await page.waitForSelector("select[name=month]");
await page.select("select[name=month]", "${month}");
await page.waitForTimeout(${delayTime});
// 日の選択
await page.waitForSelector("select[name=day]");
await page.select("select[name=day]", "${day}");
await page.waitForTimeout(${delayTime});
// 施設の選択
await page.waitForSelector("select[name=sisetu]");
await page.select("select[name=sisetu]", "${sisetu}");
await page.waitForTimeout(${delayTime});
// 照会ボタンのクリック
await page.click("input[type=button][value=照会]");
await page.waitForNavigation();
// 結果ページの待機
await page.waitForTimeout(${delayTime * 2});
`)
});
// PhantomJsCloud APIを呼ぶためのオプションを返す関数
const options = payload => ({
'method': 'post',
'payload': JSON.stringify(payload)
});
// 指定した日付と施設の空き状況をスクレイピングする関数
function scrapeFacilityAvailability(month, day, sisetu) {
try {
const response = UrlFetchApp.fetch(
endpoint(APIKEY),
options(payload(month, day, sisetu, DELAY_TIME))
);
const result = JSON.parse(response.getContentText())["content"]["data"];
return result;
} catch (error) {
Logger.log(`エラーが発生しました: ${error}`);
return null;
}
}
// 実行例
function executeExample() {
// 例: 4月1日の瑞穂アリーナ第1競技場の空き状況を確認
const result = scrapeFacilityAvailability(
"04", // 月
"01", // 日
"0261" // 瑞穂アリーナ第1競技場のコード
);
// スプレッドシートに結果を記録する例
if (result) {
const sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("A1").setValue(result);
}
}
// 複数施設の空き状況を一括で取得する関数
function scrapeMultipleFacilities() {
const facilities = [
{ code: "0261", name: "瑞穂アリーナ第1競技場" },
{ code: "0262", name: "瑞穂アリーナ第2競技場" }
];
const month = "04"; // 4月
const day = "01"; // 1日
const results = [];
facilities.forEach(facility => {
const result = scrapeFacilityAvailability(month, day, facility.code);
if (result) {
results.push({
facility: facility.name,
availability: result
});
}
// APIの制限を考慮して少し待機
Utilities.sleep(1000);
});
return results;
}