paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

pythonでクレジット支払い集計ツールを作りたい

いつの間にか4月ですね。

この時期はだんだん暑くなっていくのもあってあまり春らしさを意識せずに過ぎていってしまいます。


私はお店の支払いはクレジットか電子マネーですることがほとんどなんですが、
何にいくら使ったのかの感覚が残りづらいため、出費を意識できるものが必要だと常々考えていました。
(家計簿とか書くのはめんどくさいので無し)

そこでpythonで簡単な集計ツール作れないかなーと思い、ちょっとやってみました。

私はクレジットの支払いはvisaでやっているのですが、
管理サイトから月次で支払いの詳細がダウンロードできるのでこれを加工したいと思います。

結論: pythonだけじゃ厳しかった

csvモジュールと演算でできるかもと思っていたのですが、うまいこと集計できませんでした。
支払いの明細と金額を辞書に入れてcountとかで集計できそうな感じでしたが、加算されずに金額のみアップデートされてしまってできませんでした。
ダウンロードしたファイルのフォーマットや私の技術不足もあると思います。

おとなしくデータベースを使います

python勉強中ですが、これだけにこだわる必要はないので、おとなしく便利なデータベースを使って集計します。
サクッと集計が今回の目標なのでDBのデーモンは使わず、sqliteでチャレンジします。

  • データベースはsqlite3を使う

メインマシンであるUbuntu 16.04LTS Desktopにはデフォルトでsqlite3がインストールされていました。
sqliteとの違いがいまいちわかりませんが、とりあえずこれでいいでしょう。

  • データベースを作ります

credit.dbという名前でデータベースファイルを作ります。
ちなみに環境はvenvで仮想環境作ってます。

(python3) masashi@PC-ubuntu:~/python3/work$ sqlite3 credit.db
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.

支払い一覧はcsvでダウンロードできます。
デフォルトの形式だといろいろ面倒なので、集計用に成形してます。
日付と明細と金額のみ記載しています。

sqlite> .mode csv
sqlite> 
sqlite> .import 201801_02.csv 201801
Error: near "201801": syntax error

あれ、インポートできない。
数字のみなのがダメなのかな。

sqlite> .import 201801_02.csv t_201801

頭にt_(tableの意)をつけたら行けました。

  • 確認

わー文字化けしてる。
ファイルを調べたら文字コードはCP932となっている様です。

sqlite> select * from t_201801;
2017/11/30,"���t�[�W���p��",498
2017/12/01,"�i�F�b�n�l�@�Q�T�|�r�X�p�b�N���p��",5431
2017/12/03,"�i�b�v�X�@���t�k�C���^�[�X",10022
2017/12/03,"�C�I�����e�[��",3419

カラムで絞れるか確認。

sqlite> select name from t_201801;
Error: no such column: name
sqlite> 

このままじゃ絞れませんでした。
文字化けしてるからダメなのかな。

インポート時に変換できないか調べましたが、すぐ出てこなそうなのでGUIで修正して保存しなおし。
テーブルを削除して、再インポートします。

sqlite> drop table t_201801;
sqlite> 
sqlite> .import 201801_02.csv t_201801
201801_02.csv:37: expected 3 columns but found 1 - filling the rest with NULL
sqlite> 
sqlite> select * from t_201801;
date,name,cost #これがヘッダ
2017/11/30,"インターネットイニシアティブ",1796
2017/11/30,"ヤフージャパン",498

お、行けました!

37行目でエラーはいてますが、一旦勧めます。

sqlite> select name from t_201801;
name
"インターネットイニシアティブ"
"ヤフージャパン"

カラムで絞っても大丈夫そうですね。

pythonからつつけるようにする

都度sql叩いて集計してもいいですが、せっかくなのでpython経由で出力できるようにします。
とはいってもこっちもsql叩くだけなんだけど…

#!/usr/bin/env python3

import sqlite3

database = 'credit.db'

connection = sqlite3.connect(database)

cursor = connection.cursor()

for row in cursor.execute('select name, sum(cost) from t_201801 group by name'):
    print(row[0], row[1])

とりあえず簡単なコードです。

sqliteにアクセスしてname(明細)毎に金額を集計するだけです、

(python3) masashi@PC-ubuntu:~/python3/work$ python credit.py 
None None
イオンリテール xxxx
イトーヨーカ堂 (サインレス) xxxx
インターネットイニシアティブ xxxx
サンフエイス xxxx
スウイ―ト カヴアカヴア xxxx
スマートEX(JR東海) xxxx
ツクモパソコン本店 xxxx
ツダヌマ パルコ xxxx
ナップス 千葉北インター店 xxxx
ヤフージャパン xxxx
千石電商 秋葉原本店 1F xxxx
11月分 au電話利用料 xxxx
Bar Vie Lembranca xxxx
J:COM 2サ-ビスパック利用料 xxxx
JR東日本モバイルSuica xxxx
JR西日本 xxxx
NETFLIX.COM xxxx

できました〜!
1月支払い分の明細の集計ができましたよ。
恥ずかしいので金額は隠します。

基本機能はできましたね。

もう少し改良して使い勝手を良くしていきたいと思います。

やりたいことメモ

  • インポートするcsvファイル成形
    • 今回は手動で修正しましたが、自動でやらせたい
  • 固定費とそうでない出費を分ける
    • 文字列判定でできそう
  • Noneの行をスキップする判定を入れる
  • 出力結果のカラムを綺麗にする
  • 月ごとに出力できるようにする
    • これは引数でできそう

あと、これからインポートファイルを増やしていくにしたがってテーブルの設計も考えないとですね。
(追加か別テーブルか)