家計簿アプリZaimデータの分析・可視化基盤を作った話


私のブログからの転載です。プログラミングやソフトウェア周りの記事を書いているのでご興味あればのぞいてみてください。

この記事のまとめ

  • 家計簿アプリのZaimのデータを分析する基盤を作りましたので概要を説明しています。
  • Kibanaを使った家計の分析例を紹介しています。

背景

我が家の家計簿はZaimで付けているのですが、すべての項目を計算に使いたいわけでないので、細かい分析は手動でやっているのがこれまででした。ただ、クレジット支払いの確定は2ヶ月、3ヶ月くらいかかってしまうため、その度に集計し直すのが面倒でした。

そこで探すとinTheRye/zaim-analysis-platformというものを作られている方がおられたので、それを使ってみようとしたのですが、利用しているAirflowのパッケージが古かったりしてうまく動かないきませんでした。

そうなったらこのZaim Analysis Platformをベースに自分好みにアレンジしようというのが今回の話です。

リポジトリ

ひとまず今回作ったGitHubリポジトリを載せておきます。

利用方法

まずは利用方法から説明します。

ファイルのダウンロード

Gitリポジトリのクローンを作ります。

$ git clone https://github.com/hassiweb/zaim-analysis-platform.git
$ cd zaim-analysis-platform

Zaim用のコンフィグの作成

自身のzaim.netのID、PASS、スクレイピングしたい家計簿データの開始日を書き込んだ config.yml ファイルを airflow/app/ に作ります。

$ echo 'ID: "your_user_id"' > airflow/app/config.yml
$ echo 'PASS: "your_password"' >> airflow/app/config.yml
$ echo 'START_DATE: "2018-1-1"' >> airflow/app/config.yml

コンテナの実行

docker-composeで必要なコンテナを起動します。

$ docker-compose up -d

Airflowでのジョブの設定

http://localhost:8080 でAirflowにアクセスします。

上の赤枠のところが "Off" の状態ではタスクの実行は行われませんので "On" にします。

なお、初期設定では毎日0:00 JST (15:00 UTC)にZaimデータ更新のタスクを実行します。即座にデータ更新したい場合には下の赤枠の "Trigger Now" をクリックするとタスクが実行されます。

なお、取得データが多い場合にはデータの取得に数分かかることがありますので、画面を更新して "Recent Tasks” が "Success" になればタスクの実行が終了し、Zaimデータの更新が完了しています。

Kibanaの初期設定

http://localhost:5601 でKibanaにアクセスします。
まず初めに、Kibanaで使用するIndex Patternを作る必要があります。
下のように zaim* を読み込ませれば、Elasticsearchからデータを読み出してIndex Patternを作ってくれます。

あとはKibanaのVizualizeから表示したい項目を適当に可視化します。

データがない!となっているときがありますが画面右上の検索期間短くなっている可能性があります。デフォルトでは直近15分。データがありそうな期間に変更していください。

どのように可視化するのかわからない方は私のブログでいくつかの例をまとめていますのでそちらもご参考にしてください。

システムアーキテクチャ

上記の変更に伴って、システムアーキテクチャは下図のようになっています。基本的にはユーザー側はKibanaとAirflowのWeb UIだけ使えば十分です。

処理の流れ

もともとの処理から大きく変わっていません。もともとの作者のQiitaをご覧ください。
ただ、1点だけ変更しているのは、Elasticsearchへのデータ登録はPythonで行うように変更したので、AirflowのDAGsには1つのタスクしかありません。

主な変更点

最後にinTheRye/zaim-analysis-platformから何を変更したのか下記にまとめておきます。

1. Airflowのバージョンアップ

タスクスケジューラのApache Airflowについて、Apacheに寄贈される前のAirflowのバージョンが使われておりましたが、現在は既にApache寄贈前の関連パッケージのダウンロードができないようになっていました。

そのため、Apache Airflowにベースイメージとして zhongjiajie/docker-airflow ****を使用して、AirflowのDockerコンテナを作り変えました。

2. Airflowのアーキテクチャ変更

既存で使われていたAirflowのアーキテクチャが、分散処理用のWorkerであるCeleryが使われていたのですが、Airflowで実行するタスクは zaim.net からの毎日1回だけデータをスクレイピングで取得するだけの単純処理で、同時に複数処理を行うこともないため、Local実行に変更しました。

Apacheのアーキテクチャなどについてはこちらの記事でまとめていますのであまり知らない方はこちらをご参照ください。

3. スクレイピングで使用するSeleniumのブラウザの変更

Airflowで実行するスクレイピングのタスクで使用するSeleniumとブラウザについて、既存で使われていたものはPhantomJSが使われていましたが、こちらは既に非推奨となりサポート外となっておりますので、Chromeに変更しました。

4. Selenium Remote Controlの使用とそれ用のStandaloneサーバーのDockerコンテナの追加

上記のChromeの使用にあたって、AirflowのWorkerノードのコンテナ内にChromeをインストールするのはマイクロサービスの概念からするとあまり筋のいいやり方ではないので、Selenium Standaloneサーバーのコンテナを立ち上げ、WorkerノードからはPythonでリモートでSelenium Standaloneサーバーのブラウザを制御するようにしました。

Selenium Remote Controlの概要についてまとめていますので、ご興味あればご覧ください。

5. ElasticsearchとKibanaのバージョンアップ

ElasticsearchとKibanaのバージョンを5.5.2から最新の6.6.2にバージョンアップしました。

6. ElasticsearchにZaimのデータをストアするときにドキュメントのインデックスの追加

ここがやりたかったことでもあるのですが、zaim.net からスクレイピングしたデータには、直接的に支払・収入・振替を表す項目がなく、不便だったので新たに “payment_income” のインデックスを追加しました。“payment” (支払)、“income” (収入)、“transfer” (振替)のいずれかの値を取ります。

また、特定期間の情報だけを取ってくるために “year” と “month” のインデックスを追加しました。

トラブルシューティング

Airflowでのタスクのログの確認

Airflowでエラーが起こっている場合は、まずはログを見ましょう。

Treeを表示します。

タスクを表示します。

ログを表示します。

下は成功ログですが、失敗していたらエラーログが吐き出されていますのでそれをもとにデバッグしましょう。

今回は以上です。
最後まで読んでいただき、ありがとうございます。