12
15

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 5 years have passed since last update.

LINE Messaging API + GAS + Googleドライブ OCR で家計のスナップショットをグラフ化

Last updated at Posted at 2019-06-26

はじめに

詳細な家計簿をつけるのは億劫だけど、資産の増減くらいは最低限把握しておきたいところ。

そこで大まかな資産推移を捕捉するために、勉強がてら LINE Messaging API と GoogleAppsScript、
Google ドキュメントのOCR機能を使用して家計のスナップショットを可視化してみました。
愛用しているマネーフォワードMEの資産残高画面のスクリーンショットを撮影・bot に投稿することで
以下のような資産推移グラフを自動で作成します。
asset_graph_mosaic.png

処理の流れ

  1. マネーフォワードMEの資産残高のスクリーンショットを撮影し、LINE botに投稿
asset_ss_mosaic.jpg
  1. GAS を hook し、投稿画像を Drive に保存
  2. Google ドキュメント の OCR 機能を使用し、画像から残高部分を抜粋
  3. 加工して Spreadsheet に転記
  4. グラフを作成、その画像URLを LINE bot にて返信

という感じです。2.〜 5. の部分を GAS で自動化しています。
Google ドキュメントの OCR の精度がかなり良いため、特に苦労なく求めていた機能を実現できました。

事前準備

LINEデベロッパーへの登録やGoogle アカウントでの認証が必要になります。以下の記事などを参考にしました。

GASのなかで Drive API を呼び出す必要があるので、有効化しておきましょう。

また投稿した画像やグラフ画像の保存用にDrive上に専用フォルダを作成しておくと便利です。
このとき作成したフォルダのURL末尾の部分がコード中で使用するフォルダのIDとなります。
なお作成した画像などは都度削除しているので、このフォルダにデータが蓄積されることはありません。

コード

Code.gs
var CHANNEL_ACCESS_TOKEN = "YOUR_ACCESS_TOKEN";
var spreadsheet = SpreadsheetApp.openById("YOUR_SPREADSHEET_ID");
var sheet = spreadsheet.getActiveSheet();

function doPost(e) {
  var events = JSON.parse(e.postData.contents).events;
  var url =
    "https://api.line.me/v2/bot/message/" + events[0].message.id + "/content/";
  var image = getImage(url).getBlob();
  var fileName = Utilities.formatDate(new Date(), "Asia/Tokyo", "YYYY-MM-dd");
  var requestBody = {
    title: fileName,
    mimeType: "image/jpeg",
    parents: [{ id: "YOUR_FOLDER_ID" }]
  };

  // 投稿画像をもとにOCRにかけたドキュメントファイルを作成
  Drive.Files.insert(requestBody, image, { ocr: true });

  var folder = DriveApp.getFolderById("YOUR_FOLDER_ID");
  var doc = folder.getFilesByType("application/vnd.google-apps.document").next();
  var docId = doc.getId();
  var lines = DocumentApp.openById(docId).getBody().getText().split("\n");

  // 残高部分のみ抜粋
  var text = [];
  lines.forEach(function(l) {
    if (l.match([1-9]/)) text.push([l.slice(1)]);
  });
  folder.removeFile(doc);

  // 既に記録がある列の隣に記録
  for (var i = 1; ; i++) {
    if (sheet.getRange(1, i).getValue() != "") continue;
    sheet.getRange(1, i, 1, 1).setValue(fileName);
    sheet.getRange(2, i, text.length, 1).setValues(text);
    break;
  }

  // グラフ部分の画像URLを取得
  var graphImg = sheet.getCharts()[0].getBlob();
  folder.createFile(graphImg).setName(fileName);
  var img = folder.getFiles().next();
  var imgUrl = img.getUrl();
  folder.removeFile(img);

  reply(events[0], imgUrl);
}

function getImage(url) {
  return UrlFetchApp.fetch(url, {
    headers: {
      "Content-Type": "application/json; charset=UTF-8",
      Authorization: "Bearer " + CHANNEL_ACCESS_TOKEN
    },
    method: "GET"
  });
}

function reply(e, url) {
  var message = {
    replyToken: e.replyToken,
    messages: [
      {
        type: "text",
        text: url
      }
    ]
  };
  var replyData = {
    method: "post",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer " + CHANNEL_ACCESS_TOKEN
    },
    payload: JSON.stringify(message)
  };
  UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", replyData);
}

まとめ

LINE bot + GAS の組み合わせはちょっとしたツールを作るのに最高ですね。
今回初めて使用した OCR もかなりの精度で、発想次第でもっといろいろ面白いことできそう。
スクショの撮影・投稿も毎月○日に自動実行、できれば理想なんだけど、いい方法ないかなぁ。

参考にしたリンク

12
15
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
12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?