paloma blog

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

支出をこまめにチェックするためのスクレイピング系もろもろ(頓挫編)

コロナ中に定着してしまった自分の引きこもりを脱却すべく昨年から地元の飲み屋に通いつめ、その甲斐あって知り合いも増え一緒に遊びに行く機会が増えました。
それは良いことなのですがそのぶん出費も増えるわけです。

私はカード払いがほとんどなので月末の引き落とし日にまとめて家計簿ソフトに突っ込んで収支計算をやっているのですが、先月の支払いにビックリしてしまいました。
支払いが多かった月は翌月調整すればいいやと思っていましたが、飲み屋通いのルーティーンも増えたこともあり意外と修正が難しいです。(飲む量減らせよという意見はごもっとも)

完璧な自制が出来れば越したこと無いのですが、そもそも月一でしかウォッチしていないから調整が難しいんだと思います。

ここは週次でチェックできるようにしましょう。
もちろんブラウザを開いて確認なんて面倒なことはやらずにスクリプトを書いて解決です。

確認内容

確認するのは3つで

  1. 現金の支払い
  2. クレジット会社の明細
  3. PayPayの支払い

です。

1は家計簿ソフトのFireflyに使った都度突っ込んでいますのでこれを取ってくるだけ。
2と3はサイトにログインして明細を取ってこないと行けないのでスクレイピングですね。

最後に集計してファイルに書き出し。
サブ機ubuntuで仕掛けを作りますが、conkyに出すようにすれば目につくとこでウォッチできますね。

firefly iii

これは月次で明細をAPI経由で突っ込んでるので勝手知ったるものです。 APIのパスを変えるだけでOK。
スクリプトはこんな感じです。

start=$(date +"%Y-%m-01")
current=$(date +"%Y-%m-%d")

spent=$(curl -s -X GET http://10.0.1.1/api/v1/summary/basic -H "accept: application/json" \
-H "Authorization: Bearer $(cat '/xxx/firefly token.txt')" -H "Content-Type: application/json" \
-d "{\"start\":\"$start\", \"end\":\"$current\"}" | jq '."spent-in-JPY"."monetary_value"' | cut -d '.' -f 1 | sed -e 's/"//'  -e 's/-//')

echo $spent
❯ ./scripts/firefly_sum.sh
14660

3/14時点で現金払いだけで14660円使ってます。
まあいろいろお出かけしたからね。

conkyで拾うようにしてこんな感じになります。

これなら嫌でも目に入る。


ここから頓挫

クレジット明細

これはカード会社のサイトに行って現在の支払額の値を取ってきます。
スクレイピングと言いながらログイン処理等イチから書くのは大変なのでseleniumを使います。

とログインまでの処理を書いたのはよいのですが、selenium経由だとログインページから進まずタイムアウトします。
ブラウザにはnavigator.webdriverという自動制御のフラグのパラメータがあり、これでbotかどうかの判別になるようです。
なんかこれで止められている気がする。 しかしundefinedにするコマンド見つけたけど事象変わらず。他にも止めているパラメータがあるんでしょうか。うーむ、わからん。

案2

スクレイピングがだめならpyautoguiでブラウザ操作だ。
と思いましたがubuntu22.04ではマウスが動かず…

その手の記事を見るとWaylandではなくXorgを使えば動くとありました。
Xウィンドウのマネージャ変えてまで動かしたいかというと微妙です。

今はCLIでブラウザとURL指定してサイトに一発で飛ぶくらいしか対策がありませんね。

PayPay

PayPayもクレジット払いなのですが、紐付いているpaypayカードのサイトに行くとアプリで見ろと誘導されます。
これもだめか、スマホ都度見るしかないかな。
APIとかないかなあ。

これも実現できずと。

まとめ

結局成功したのはFireflyの支出額の取得のみでした。
まあクレジット系の支払いは増減あれどだいたい平均には落ち着くので現金支出のウォッチができるだけでもマシになったか。

今回は半分以上実現できず頓挫編にしましたがいつか解決を目指します。

gitのbranchにcheckoutしたらcommitが消えたから復旧

例のPayPay集計アプリを作っていた際にコードをまとめてロールバックをしようと思ってファイル名指定無しでcheckoutしてしまいました。
ブランチ名がハッシュの値になってしまったのですがこんなもんかと思いcommitを進めていました。
あるときgithubにpushしようと思って本来のブランチにcheckoutしたら進めていたぶんのcommitが消えてしまいました。

やばい!書き直し!?となったので早速ググりました。

事象

ターミナルのログが流れてしまったのでHistoryからの振り返りになります。

ディレクトリに3つのファイルがあります。

ls
__pycache__  app.py  main.py  my.kv

これらをまとめて直前のcommitにロールバックしようと思って以下を打ちました。

git checkout cd40a80

これを実行してからファイルが戻んないなーと思って何回かgit log見ながら、

git checkout cd40a80
git status
git checkout cd40a80 main.py my.kv app.py
git checkout 517f9c7 main.py my.kv app.py
git checkout 6003475 main.py my.kv app.py
git checkout d7d7381 main.py app.py my.kv
git checkout HEAD main.py app.py my.kv

いろいろコミット位置を変更しちゃったんですよね。

これで先日の処理を追加してpushしようかなとブランチに戻ったらコミットが消えてしまいました。

git checkout kivy

今のログからですが、

4889656 (HEAD -> kivy_local, origin/kivy, kivy) Changed for android path
9aaf0b8 Add exit button of top page
cb67e4b Changed top page design
68f58db Changed button layout
06f4952 Add exit button
a2a91b8 add return button
5d1f50c Change window size
9325935 import japanize_kivy
c7d7f8f Successfully drew graph another screen
b60900a Updated kivy garden matplotlib
# ここから上のコミットが消えた
d7d7381 Fixed path
6003475 Fixed import module name
517f9c7 Enable view plt.plot for Ubuntu desktop
613a809 Add matplotlib

という状況になりました。

復旧

ありがたいことにこの手の復旧もちゃんと方法がありました。 この辺を参考に復旧できました。

detached HEAD から脱出する方法を git の内部構造から探る #Git - Qiita

新しいブランチを切ってそれにcommitし直せばOK。
マージもして完了です。

git checkout kivy_local
git branch kivy_local
git merge kivy_local

こうなった原因はハッシュを指定してcheckoutしたことでブランチを参照していない状態でcommitを進めてしまっていた様です。
ファイルをロールバックする時に一編やろうと思ってファイル名の引数無しで実行してしまったんですね。

git checkout cd40a80  # これで全部戻ると思ってた
git checkout main.py my.kv app.py # おとなしくこれで良かった

ブランチ名とハッシュ値を同じと思ってましたが別物の様です。 仕組み共々もっとgit勉強しないとな。

PayPayの支払いデータを自分で集計したい4

年を跨いでしまいましたがタイトルのツールについて、PC環境ですがkivyで動くようになりました。
レイアウトとwindowサイズをいじってスマホ画面に近くしてます。

画面

トップページ

シンプルですがトップ画面です。

下画面のFile chooserでダウンロード済みの明細を選択して出力させると、

明細の出力とグラフ化

画面遷移して月次の明細と支払いTOP3のグラフが出ます。
一応詳細はマスクしておきます。

デザインはおいといて望む感じのものが出来ました。
合計額も上画面に出しておくか。

ここまでの道のり

グラフの出力に手間取って時間かかってしまいました。

kivyでグラフを出すサンプルの記事は沢山ありますが、私はグラフを別モジュールで作成するようにしたので描画どうすればいいのって感じで試行錯誤でした。
kivy側で作成するとかいろいろコード直しましたが、エラー内容を比較するとどちらで作っても同じで作成済みのデータをWidgetに渡すだけでよかった様です。

コードこの辺です。

main.py

class Main(Screen):

    def open(self, path, filename):
        with open(os.path.join(path, filename[0]), encoding='utf-8-sig') as f:
            csvfile = f.readlines()

        return csvfile

    def createdb(self, afile):
        con = sqlite3.connect(':memory:')
        cur = con.cursor()

        app.insertData(afile, cur)
        dates, contents, t = app.shapeingData(cur)

        res = ''
        for x in contents:
            res += f'{x[0]} {x[1]} {x[2]} {x[3]}\n'

        self.manager.get_screen('analize').ids.result.text = res

        p = app.createGraph(dates, cur)  # 別の自作モジュールでグラフ作成

        widget = FigureCanvasKivyAgg(p.gcf())

        self.manager.get_screen('analize').ids.plot.add_widget(widget) # 別画面のWidgetに渡す
        #ids.plot = p.show()
        con.close()

    pass

my.py

<Main>:
    name: 'main'
    id: main

    BoxLayout:
        (略)
        Button:
            text: '明細選択'
            on_release:
                main.createdb(main.open(fc.path, fc.selection))
                root.manager.current = 'analize' # これで別画面に遷移
            size_hint_y: 0.2
        FileChooserListView:
            id: fc
            path: '../ドキュメント/paypay/'
            filters: ['*.csv']


<Analized>:
    name: 'analize'

渡すのに失敗していたのはkivy gardenのバグの様で出力出来てなかっただけでした。
アップデートして無事に動きました。発見した人に感謝です。

そのページ(確かstack overflow)を探しているのですが見つからないので発見したら載せます。

バグ

出力したら戻って別の月の出力も続けて出来るようにしようと思ってますが2回目を選択するとグラフが混ざってしかも2つ表示されます。

グラフの変数をクリアしてないからだと思いますが今DBから取得してそのままグラフを作ってるので関数を分けないと難しそうだ。

これは後回しにして次はandroid用にビルドします。(すでに失敗してるが)


一応リポジトリはこちら

github.com

そろそろdotfilesの管理もしておこう

家のubuntu desktopは2代目ですがwslの環境も入れるとそこそこなLinuxの台数を渡り歩いてきた気がします。

移行の度にDriveに保存してある設定ファイルからリストアしていて移行は出来ていますがスマートではありません。
やはりバージョン管理したいところなのでdotfileのリポジトリを作ろうと思います。

dotfile管理のベストプラクティス

初めての管理なのでベストも何も無いのですがArch wikiの記事が良さそうだったのでこちらで作ります。

ドットファイル - ArchWiki

やり方は

  1. bareのリポジトリを作る
  2. リポジトリに1を指定、workディレクトリをhomeに指定してgitを実行

というものです。

これだと管理したいファイルだけ指定しておけば良いということらしいです。

良くみる記事だとdotfileフォルダを作って本体の設定ファイル置いてシンボリックリンク張って、というのがほとんどでリンク用のスクリプトとか書くのめんどくさいと思って着手出来ませんでした。

ちなみにハードリンクを使う記事が無かったのですが都合が悪いんですかね?
一回挑戦してみればよかった。

リポジトリ作成

wikiに沿って作成。

❯ git init --bare ~/.dotfiles
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint:   git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint:   git branch -m <name>
Initialized empty Git repository in /home/masashi/.dotfiles/
❯ alias config='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
❯ config config status.showUntrackedFiles no

使ったことないオプションだらけですが

  • bare
  • work-dir
    • そのままの意味
  • showUntrackedFiles

らしい。一応調べたけど単語で何となくわかる。
今後はconfigコマンドで操作していくことになります。

homeがワークディレクトリだから必要なファイルを選んでcommitしていく感じですね。
デスクトップまわりはどうするか考えますが.bashrc .zshrc .conkyrc .vimrc辺りは必ず欲しいです。

とりあえずこの辺をcommit。

❯ config add .bashrc .p10k.zsh .vimrc .zshrc .zshrc.pre-oh-my-zsh
❯ 
❯ config status
ブランチ master

No commits yet

コミット予定の変更点:
  (use "git rm --cached <file>..." to unstage)
    new file:   .bashrc
    new file:   .p10k.zsh
    new file:   .vimrc
    new file:   .zshrc
    new file:   .zshrc.pre-oh-my-zsh

Untracked files not listed (use -u option to show untracked files)
❯ config commit -m "First commit"
[master (root-commit) d09968a] First commit
 5 files changed, 2088 insertions(+)
 create mode 100644 .bashrc
 create mode 100644 .p10k.zsh
 create mode 100644 .vimrc
 create mode 100644 .zshrc
 create mode 100644 .zshrc.pre-oh-my-zsh

commit後のリポジトリ

リポジトリはどうなってるのかなっと。

ls .dotfiles
COMMIT_EDITMSG  branches  description  index  logs     refs
HEAD            config    hooks        info   objects

bareだからファイルが無いですね。

clone

PCを新調した体で1個ディレクトリ下げてcloneしてみます。

mkdir testhome
❯ cd testhome
❯ lsls -a
.  ..
❯ git clone ../.dotfiles
Cloning into '.dotfiles'...
done.
❯ ls -a
.  ..  .dotfiles
❯ ls -a .dotfiles
.  ..  .bashrc  .git  .p10k.zsh  .vimrc  .zshrc  .zshrc.pre-oh-my-zsh

ちゃんとファイルがありますね。
homeで実行すれば上書いてくれるのかな?
こうならデスクトップ環境もリストアできそうなのでリポジトリに入れるべきですね。

push(失敗)

最後にGithubに上げようと思いましたがpermission deniedでpushできず...
これは別の機会にチャレンジします。

2023下半期見た映画メモ

2023年も終わりということで後半のまとめです。

一応記録としてXにもポストしてますがAPIの関係でメイン管理はGithub pagesになりました。
jekyllで作ってるので今回は記事のディレクトリから抜いておさらいです。

masashi69.github.io

下半期見た映画

API経由での取得からただのファイル名の抽出になりました。
成形はほどほどにls結果こんなもんでしょう。

ls _posts/2023-(0[7-9]|1[0-2])*.md | grep -oP 'posts/\K.+?(?=.md)' | nl
     1  2023-07-02-Never Back Down 2: The Beatdown
     2  2023-07-03-John Wick: Chapter 2
     3  2023-07-09-Gold Brick
     4  2023-07-17-The Guilt Trip
     5  2023-07-17-The Irishman
     6  2023-07-23-Baseball Girl
     7  2023-07-23-Proud Mary
     8  2023-07-30-The Gray Man
     9  2023-08-06-The Wrong Missy
    10  2023-08-08-Ibiza
    11  2023-08-20-Jumper
    12  2023-08-27-Peppermint
    13  2023-09-03-D.E.B.S.
    14  2023-09-10-Burn After Reading
    15  2023-09-17-Battlefield Earth
    16  2023-09-18-Yes Man
    17  2023-09-19-The Out-Laws
    18  2023-09-30-Altrimenti ci arrabbiamo
    19  2023-10-08-A Man Apart
    20  2023-10-09-Catfight
    21  2023-10-14-Metal Lords
    22  2023-10-30-The After Party
    23  2023-11-04-Gemini Man
    24  2023-11-12-Source Code
    25  2023-11-23-Take Me
    26  2023-11-26-Unicorn Store
    27  2023-12-10-Scott Pilgrim vs. the World
    28  2023-12-10-The 355
    29  2023-12-17-SuperFly
    30  2023-12-25-Freaks: You are One of Us

今回は30件でした。
今年は引きこもらず外に出ようと決めたので一年通してあまり映画見れてないです。
しかも後半につれ外出の頻度が上がったので映画を見る方はいいのか悪いのかだいぶ減ってしまいました。

下半期ベスト3

今回の結果はこちら。

  1. Burn after reading (2008)
    CIAの暴露本を書こうとしたデータが巡り巡ってスポーツジムのスタッフが見つけてしまいこれをネタに金銭要求を行う話です。
    ちょっとした悪ふざけが事態をどんどん大きくしてしまい複数組織が絡み合う複雑な事件に発展してしまいました。
    この盛り上がり方が非常に面白かったです。
  2. Yes man (2008)
    ジム・キャリー主演の有名映画ですね。主人公の明るい感じが凄くいいです。頼まれ事に全てイエスと答える話ですが人生なんでもチャレンジですね。
  3. My wrong missy (邦題: 僕のミッシー 2020)
    主人公の慰安旅行の同行に狙っていた女性とは違う同名のミッシーを誘ってしまうという話です。
    言動がだいぶイカれてるミッシーですがたまにこういうコメディ全降り系も楽しいです。ローレン・ラプカスが非常にはまり役でした。

メタルロード、バトルフィールドアースも結構よかったですが次点です。

まとめ

今回見た件数は減りましたが覚えている作品が多くこういうペースも割とよいのではと思います。
もちろん見まくったほうが面白い作品に出合う率が上がりますが何事もバランスですね。
来年もバランスよく頑張りましょう。

PayPayの支払いデータを自分で集計したい 番外編

タイトルのツールを製作中ですが、明細が溜まったので一度計算してみたいと思います。
今回はDB(sqlite3)に入れて集計してみます。

ツールはサブPCのUbuntu上で作ってるのでその環境で動かします。

スキーマ

前回作ったpythonコードをちょっと修正してそれ経由でCSV突っ込んでます。
なのでカラムは最低限のものしかありません。
レコードは250です。

sqlite> .schema
CREATE TABLE payment_2023 ("利用日/キャンセル日" TEXT,"利用店名・商品名" TEXT, "支払総額" TEXT);
sqlite> SELECT count("利用日/キャンセル日") FROM payment_2023 ;
250

シェルスクリプト

何回かに分けてデータを取り出します。
年次とか月ごととか。
DBは本職じゃないのでもっといい書き方があると思います。
改行無しの1行で書いてしまった。見にくくてすみません。

#!/bin/bash

MIN_DATE=$(sqlite3 paypaydb.db "SELECT MIN(\"利用日/キャンセル日\") FROM payment_2023;")
MAX_DATE=$(sqlite3 paypaydb.db "SELECT MAX(\"利用日/キャンセル日\") FROM payment_2023;")

echo "期間: ${MIN_DATE} ~ ${MAX_DATE}"

#年次
echo "===== 年次明細 ====="
sqlite3 paypaydb.db "SELECT strftime('%Y', \"利用日/キャンセル日\"), sum(支払総額), count(利用店名・商品名) FROM payment_2023;"
#年次 店ごと
echo "===== 店ごとの年次明細 ====="
sqlite3 paypaydb.db "SELECT 利用店名・商品名, sum(支払総額), count(利用店名・商品名) FROM payment_2023 GROUP BY 利用店名・商品名 ORDER BY count(利用店名・商品名) DESC"
#月次 店ごと
echo "===== 月ごとの明細 ====="
sqlite3 paypaydb.db "SELECT strftime('%Y-%m', \"利用日/キャンセル日\"), 利用店名・商品名, sum(支払総額), count(利用店名・商品名) FROM payment_2023 GROUP BY 利用店名・商品名, strftime('%Y-%m', \"利用日/キャンセル日\") ORDER BY \"利用日/キャンセル日\";"
#決済回数
echo "===== 一日あたりの最大決済回数 ====="
sqlite3 paypaydb.db "SELECT \"利用日/キャンセル日\", 利用店名・商品名, max(count_stores), sum_pay FROM (select \"利用日/キャンセル日\", 利用店名・商品名, count(利用店名・商品名) as count_stores, sum(支払総額) as sum_pay FROM payment_2023 GROUP BY \"利用日/キャンセル日\", 利用店名・商品名 ORDER BY count_stores, sum_pay DESC) GROUP BY 利用店名・商品名 ORDER BY max(count_stores) DESC;"

出力

動かしてみます。
例によって通ってる店、地名入る店はマスクしてます。
全角なのを修正すればよかった、が、まあ一旦いいでしょう。

❯ bash summary.sh
期間: 2023-05-22 ~ 2023-10-29
===== 年次明細 =====
2023|174105|250
===== 店ごとの年次明細 =====
PayPay 町かど酒場XXXX|119150|233
PayPay XXXX Dining|15800|7
ヤフージャパン|2540|5
PayPay km国際自動車T1 羽田|16050|1
PayPay KOREAN DINING|15090|1
PayPay XXXX眼科|1700|1
PayPay XXXX商店|755|1
PayPay ハリケーン|3020|1
===== 月ごとの明細 =====
2023-05|PayPay 町かど酒場XXXX|5700|11
2023-05|ヤフージャパン|508|1
2023-06|PayPay XXXX商店|755|1
2023-06|PayPay XXXX Dining|3900|2
2023-06|ヤフージャパン|508|1
2023-06|PayPay 町かど酒場XXXX|11600|22
2023-07|PayPay XXXX Dining|3800|1
2023-07|PayPay XXXX眼科|1700|1
2023-07|ヤフージャパン|508|1
2023-07|PayPay 町かど酒場XXXX|19150|38
2023-08|PayPay km国際自動車T1 羽田|16050|1
2023-08|PayPay 町かど酒場XXXX|21600|42
2023-08|ヤフージャパン|508|1
2023-09|PayPay 町かど酒場XXXX|19900|40
2023-09|PayPay KOREAN DINING|15090|1
2023-09|PayPay XXXX Dining|4200|2
2023-09|ヤフージャパン|508|1
2023-10|PayPay XXXX Dining|3900|2
2023-10|PayPay ハリケーン|3020|1
2023-10|PayPay 町かど酒場XXXX|41200|80
===== 一日あたりの最大決済回数 =====
2023-10-15|PayPay 町かど酒場XXXX|8|4000
2023-08-11|PayPay km国際自動車T1 羽田|1|16050
2023-09-24|PayPay KOREAN DINING|1|15090
2023-07-08|PayPay XXXX Dining|1|3800
2023-07-16|PayPay XXXX眼科|1|1700
2023-06-10|PayPay XXXX商店|1|755
2023-10-29|PayPay ハリケーン|1|3020
2023-05-31|ヤフージャパン|1|508

わりかし望み通りのいい感じの出力ができました。
本当はテーブルモードで出力したいのですが日本語が入るとレイアウトがずれるのでデフォルトのままです。

自作ツールなのでカラムの内容はわかりますが、ヘッダも出力させるほうががいいな。

振り返り

年次とは言ってますがPayPay使い始めたのは今年5月からなのと先月の明細までしかないのでこの時点では実質5ヶ月分の結果ですね。
それでも17万使ってます。うーむ。
PayPayはカード使えない飲み屋でしか使わないのでなかなか飲んでます。

10月は例の立ち飲み屋で計80品も頼んでますね。
週3で行っても平均一回6~7品。やはり飲み過ぎだね。
通う日にちか頼むペースをちょっと控えないとですね。

まとめ

というわけで行いを振り返りつつ今後の戒めができました。
集計ツール作ったのでこれでいいじゃんという気もしますがアプリで明細をダウンロードしてそのまま確認できるようにするのが目標なので、アプリ化は引き続きやっていきたいと思います。

本シリーズ

PayPayの支払いデータを自分で集計したい1 - paloma blog

PayPayの支払いデータを自分で集計したい2 - paloma blog

PayPayの支払いデータを自分で集計したい3 - paloma blog

PayPayの支払いデータを自分で集計したい3

今回は前回の集計をグラフ化してみます。
②の部分ですね。

  1. ツール単体で集計
  2. 集計結果を可視化
  3. スマホアプリ用にビルド

追記分はこちら。
matplotlibに読ませる様のリストを作成してます。

sqlで出したものをまたリストにいれるというマヌケな処理になってしまいました。
綺麗に出来る方法はあるものか...

diff --git a/app.py b/app.py
index 45d6cf1..04bfc50 100644
--- a/app.py
+++ b/app.py
@@ -40,48 +40,13 @@ def main():
                  count("利用店名・商品名") FROM pay GROUP BY "利用日/キャンセル日", \
                  "利用店名・商品名" ORDER BY "利用日/キャンセル日"')
 
-    datelist = list()
     for x in cur.fetchall():
         print(*x)
-        datelist.append(x[0])
-
-    datelist = list(set(datelist))
-    datelist.sort()
 
     cur.execute('SELECT sum("支払総額") FROM pay')
     # Use 'format' for use astarisk
     print('Total: {}'.format(*cur.fetchone()))
 
-    # Top 3 stores that paid most
-    cur.execute('SELECT "利用店名・商品名", count("利用店名・商品名") FROM pay GROUP BY "利用店名・商品名" ORDER BY count("利用店名・商品名") DESC')
-
-    top3 = list()
-    for x in cur.fetchall()[:3]:
-        top3.append(x[0])
-
-    no1_list = list()
-    no2_list = list()
-    no3_list = list()
-
-    for i,x in enumerate(top3):
-        cur.execute('SELECT "利用日/キャンセル日", ?, sum(CASE WHEN "利用店名・商品名" = ? THEN "支払総額" ELSE 0 END) FROM pay \
-                    GROUP BY "利用日/キャンセル日", ? ORDER BY "利用日/キャンセル日"', [x,x,x])
-
-        # Create paymant list
-        for y in cur.fetchall():
-            if i == 0:
-                no1_list.append(y[2])
-            elif i == 1:
-                no2_list.append(y[2])
-            else:
-                no3_list.append(y[2])
-
-    i = 0
-    for t in [no1_list, no2_list, no3_list]:
-        if len(t) != 0:
-            print(datelist, t, f'label={top3[i]}')
-            i += 1
-
     con.close()
 
 if __name__ == '__main__':

支払い合計のTOP3を出してグラフ用のリストに渡す様にしました。

動かすと以下の出力になります。

❯ python app.py ../ドキュメント/paypay/detail202311\(5569\).csv
2023-09-30 ヤフージャパン 508 1
2023-10-04 PayPay 町かど酒場XXXX 3200 6
2023-10-06 PayPay XXXX Dining 1900 1
2023-10-07 PayPay 町かど酒場XXXX 2150 4
2023-10-08 PayPay 町かど酒場XXXX 2700 6
2023-10-09 PayPay 町かど酒場XXXX 1900 4
2023-10-12 PayPay 町かど酒場XXXX 2300 5
2023-10-13 PayPay 町かど酒場XXXX 1150 2
2023-10-14 PayPay 町かど酒場XXXX 3700 8
2023-10-14 PayPay XXXX Dining 2000 1
2023-10-15 PayPay 町かど酒場XXXX 4000 8
2023-10-16 PayPay 町かど酒場XXXX 1450 2
2023-10-18 PayPay 町かど酒場XXXX 950 2
2023-10-20 PayPay 町かど酒場XXXX 2200 4
2023-10-21 PayPay 町かど酒場XXXX 3500 6
2023-10-22 PayPay 町かど酒場XXXX 3900 7
2023-10-26 PayPay 町かど酒場XXXX 3950 8
2023-10-27 PayPay 町かど酒場XXXX 950 2
2023-10-28 PayPay 町かど酒場XXXX 2700 5
2023-10-29 PayPay ハリケーン 3020 1
2023-10-29 PayPay 町かど酒場XXXX 500 1
Total: 48628
['2023-09-30', '2023-10-04', '2023-10-06', '2023-10-07', '2023-10-08', '2023-10-09', '2023-10-12', '2023-10-13', '2023-10-14', '2023-10-15', '2023-10-16', '2023-10-18', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-26', '2023-10-27', '2023-10-28', '2023-10-29'] [0, 3200, 0, 2150, 2700, 1900, 2300, 1150, 3700, 4000, 1450, 950, 2200, 3500, 3900, 3950, 950, 2700, 500] label=PayPay 町かど酒場XXXX
['2023-09-30', '2023-10-04', '2023-10-06', '2023-10-07', '2023-10-08', '2023-10-09', '2023-10-12', '2023-10-13', '2023-10-14', '2023-10-15', '2023-10-16', '2023-10-18', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-26', '2023-10-27', '2023-10-28', '2023-10-29'] [0, 0, 1900, 0, 0, 0, 0, 0, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] label=PayPay XXXX Dining
['2023-09-30', '2023-10-04', '2023-10-06', '2023-10-07', '2023-10-08', '2023-10-09', '2023-10-12', '2023-10-13', '2023-10-14', '2023-10-15', '2023-10-16', '2023-10-18', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-26', '2023-10-27', '2023-10-28', '2023-10-29'] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3020] label=PayPay ハリケーン

下三行が追加したコードで、日付リスト・各日毎の支払金額が合計金額の多い店舗順に出てきます。
このフォーマットをmatplotlibに読ませればグラフ化できます。

jupyterlab

グラフや画面系の確認はjupyterlabがいい感じに検証できるのでこちらを使います。
いきなりですが先程の出力結果をちょっと修正してmatplotlibに読ませるとこうなります。

明細の都合上日本語化モジュールいれたのとフォントサイズいじってます。

import matplotlib.pyplot as plt
import japanize_matplotlib

datelist = ['2023-09-30', '2023-10-04', '2023-10-06', '2023-10-07', '2023-10-08', '2023-10-09', '2023-10-12', '2023-10-13', '2023-10-14', '2023-10-15', '2023-10-16', '2023-10-18', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-26', '2023-10-27', '2023-10-28', '2023-10-29']

top = [0, 3200, 0, 2150, 2700, 1900, 2300, 1150, 3700, 4000, 1450, 950, 2200, 3500, 3900, 3950, 950, 2700, 500] 
two = [0, 0, 1900, 0, 0, 0, 0, 0, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
thi = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3020] 

plt.bar(datelist, top, label='町かど酒場XXXX')
plt.bar(datelist, two, label='XXXX Dining')
plt.bar(datelist, thi, label='ハリケーン')

plt.title('今月のPayPay支払い')
plt.ylabel('円(¥)')
plt.xticks(rotation=45)
plt.legend(loc='upper left', ncols=3, fontsize=8)
plt.tick_params(labelsize=7)
plt.ylim(0, max(top) * 1.5)
plt.show()

OK。いい感じにグラフできました。
店舗ごとの並列棒グラフにするつもりでしたが合計と割合が分かるしこの積み上げ棒グラフままでもいいか。

今後

月ごとのテーブル、グラフ出力と基本的な処理は出来たので一旦こんなものでいいでしょう。
コードはもう少し成形しますがこれからKivyに連携させるという結構大変な作業が待ってます。