1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GASで定期的にWebサイト上のテーブルのデータをkintoneに追加する

Last updated at Posted at 2021-10-01

毎日のように息子からコロナ感染者数を聞かれるので、
ここ2週間ほど毎日市のホームページのコロナ感染者のところをコピペしてExcelに貼り付け加工して、
kintoneに読み込ませる・・・という作業をしていました。

ただただ面倒だったので、1日1回、GASでスクレイピングしてkintoneに登録するという仕組みを作ってみました。

⚠⚠ホームページで発表された内容が変わってしまったら使えなくなっちゃいます。

アプリの準備

最初にExcelでアプリを作成したのでドロップダウンが何個かあります。
ほぼホームページにある通りのフィールド名にしてます。
フィールドコード=フィールド名にしています。

フィールド種類 フィールドコード 備考
数値 症例番号 重複禁止
日付 発症日 発症した日。日付以外が入っていたら発表日を入れる。
数値 クラスター 今回、GASからの登録は想定してない👀
日付 発表日 発表があった日
ドロップダウン(文字列のほうがいいかも) 年代 10代未満~90代
ラジオボタン 性別等 男性・女性
ドロップダウン(文字列のほうがいいかも) 重症度 軽症・無症状・中等症・・・・など (文字列のほうがいいかも?)
文字列(1行) 職業
文字列(1行) 居住地
数値 濃厚接触者 市内の濃厚接触者の症例番号。特記事項を書き換えて使っている
文字列(1行) 備考 発症日=発表日のときは「発表日」とする

image.png

お好みで関連レコードを追加してもいいかも?
クラスターのアプリは想像してつくってね👀
image.png

グラフの例

👀発症日グラフ
発表日ではなくて発症日で感染者数を見たい場合はこんな感じ。
備考が「発表日」のレコードを除いてグラフにする。

image.png

👀年代別円グラフ
年代別に見たいときはこんな感じ。

image.png

他にも工夫してグラフをつくってみてね👀✨✨

Google Apps Script (GAS)

ライブラリに下記を追加します。
image.png

Parser
公式のサイトがわからないですが、ご存知のかたいらっしゃったら教えて下さい👀💦
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

KintoneManager
kintone とGoogle Apps Script連携で紹介されている素敵ライブラリです。
1M8DHQSWWGOM2RSRjDZmylHMl03nZHnliaVMGMk84m6jQ05ditPBTCSM8

コードを書く

function myFunction() {

  // 久留米市の感染者9月のページ
  const url =
    "https://www.city.kurume.fukuoka.jp/1070kenkou/2040hokeneisei/3005cov2019/4309patient/index.html";
  const html = UrlFetchApp.fetch(url).getContentText("UTF-8");
  const urlList = Parser.data(html).from('<a href="2021-').to('">').iterate();

  // 感染者ページのリンクの一番上のやつが最新
  const todayUrl =
    "https://www.city.kurume.fukuoka.jp/1070kenkou/2040hokeneisei/3005cov2019/4309patient/2021-" +
    urlList[0];
  const todayHtml = UrlFetchApp.fetch(todayUrl).getContentText("UTF-8");
  const todayDataHTML = Parser.data(todayHtml)
    .from("<tr>")
    .to("</tr>")
    .iterate();
  // 発表日は今日
  const today = new Date();
  const todayStr =
    today.getFullYear() +
    "-" +
    ("00" + (today.getMonth() + 1)).slice(-2) +
    "-" +
    ("00" + today.getDate()).slice(-2);
  
  // 今日の感染者データの配列を作る。kintoneに登録できるようにhtmlを加工します。
  let todayData = [];
  todayDataHTML.forEach((v) => {
    // 苦し紛れにhtmlを整理する。もっといいやり方ありそう。
    v = v.replace(/\r?\n/g, "");
    v = v.replaceAll("<br>", "");
    v = v.replaceAll("th", "td");
    v = v.replaceAll(' scope="col"', "");
    v = v.replace("特記事項", "濃厚接触者");
    v = v.replace('</td><td style="text-align:left;">', "</td><td>");

    const todayDataRow = v.split("</td><td>");
    const b = todayDataRow.map((w, idx) => {
      w = w.replace("<td>", "");
      w = w.replace("</td>", "");

      // 発症日不明などの場合は発表日(今日の日付)を入れるようにする。
      if (idx === 5 && w != "発症日") {
        if (!w.match(/(\d+)(\d+)日/)) {
          w = todayStr;
        } else {
          const matched = /(\d+)(\d+)(\d+)日/.exec(
            today.getFullYear() + "" + w
          );
          w =
            matched[1] +
            "-" +
            ("00" + matched[2]).slice(-2) +
            "-" +
            ("00" + matched[3]).slice(-2);
        }
      }
      // 市内の濃厚接触者だけ症例番号残して他の文字は削除。
      if (idx === 7 && w != "濃厚接触者") {
        if (w.match(/^市.*/)) {
          w = w.replace(/[^0-9]/g, "");
        } else {
          w = "";
        }
      }
      return w;
    });
    todayData.push(b);
  });

  const newRecords = [];
  todayData.forEach((r, idx) => {
    if (idx === 0) {
      return;
    }
    const rec = {
      症例番号: { value: r[0] },
      年代: { value: r[1] },
      性別等: { value: r[2] },
      居住地: { value: r[3] },
      職業: { value: r[4] },
      発症日: { value: r[5] },
      重症度: { value: r[6] },
      濃厚接触者: { value: r[7] },
      発表日: { value: todayStr },
      備考: { value: r[5] === todayStr ? "発表日" : "" }, // 発症日が今日の日付のときは備考に発表日と書いておく
    };
    newRecords.push(rec);
  });

  // KintoneManagerを使う準備
  const subdomain = "【サブドメイン】";
  const apps = {
    YOUR_APP_NAME1: {
      appid: "【アプリID】",
      name: "久留米市コロナ感染者",
      token: "【APIトークン】",
    },
  };
  const kintone_manager = new KintoneManager.KintoneManager(subdomain, apps);
  // アプリにデータを登録
  const response = kintone_manager.create("YOUR_APP_NAME1", newRecords);
  const code = response.getResponseCode();
  console.log(code);
}


トリガーの設定

久留米市のホームページの更新はだいたい17時台なので、18時~19時頃に動くように設定します。
image.png

まとめ

初めてスクレイピングというものにチャレンジしてみましたが、
スクレイピングとはこんな地道な作業なのか!?と思いました。
もっといいやり方があるのではないか?と疑っています。

スクレイピングしたいホームページに合わせてhtmlを加工する必要があると思いますので。
そこは工夫してやってみてね!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?