【SUMUMA】Pythonで家計簿データを取得

[SUMUMA](https://sumuma.com/)という家計簿サービスがあり愛用しています。csvの入出力機能付き・[API](https://qiita.com/uichi/items/bd4e928cde1d714ffe5b)対応で、なんと無料で使えます。自分は普段スマホで記録→月末にpythonでAPIを用いてデータ取得・まとめという形で利用しているので、今回はその方法を紹介したいと思います。

# はじめに

[こちらのサイト](https://sumuma.com/swagger/)に飛んで、Authorizeボタンをクリックします。SUMUMAのメールアドレスとパスワードを入力してAuthorizeしたら、試しにexpendituresのGETを開いて、Try it out→pageに1を入力→Executeとしてみます。すると、

```javascript
curl -X 'GET' \
  'https://sumuma.com/api/expenditures/?page=1' \
  -H 'accept: application/json' \
  -H 'authorization: [ここの文字列を記録しておく]' \
  -H 'X-CSRFToken: [ここの文字列を記録しておく]'
```

という出力とRequest URL、1page目の家計簿データが画面上に出力されます。入出力のイメージはざっとこんな感じです。

# pythonでAPIを叩く

自分は以下のようなclassを作って使っています。initの中身は書き換えてください。

```python
import requests
import pandas as pd

class sumumaAPI:
    
    def get_requests(self, url, page):
        res = requests.get(f'{url}/?page={page}', headers=self.headers)
        return res.json()['results']
    
    def __init__(self):
        # 初期設定
        self.accept = 'application/json'
        self.authorization = '先程のauthorization:の文字列'
        self.token = '先程のX-CSRFToken:の文字列'
        self.headers = {'accept':self.accept, 'authorization':self.authorization, 'X-CSRFToken':self.token}
        # url
        self.url = 'https://sumuma.com/api'
        self.url_expenditures = f'{self.url}/expenditures'
        self.url_incomes = f'{self.url}/incomes'
        self.url_categories = f'{self.url}/categories'
        # 分類
        df = []
        for dic in self.get_requests(f'{self.url_categories}', 1):
            df.append((dic['label'], dic['id'], dic['name']))
        df = pd.DataFrame(df, columns=['label', 'id', 'name'])
        self.categories = df.set_index(['label', 'id'], drop=True)['name']
        
    # page指定で収入データを取得する
    def get_incomes(self, page):
        df = []
        for dic in self.get_requests(self.url_incomes, page):
            df.append((dic['event_date'], self.categories['income'][dic['category']], dic['amount'], dic['memo']))
        df = pd.DataFrame(df, columns=['date', 'category', 'amount', 'memo'])
        df['date'] = pd.to_datetime(df['date'])
        return df
    
    # page指定で支出データを取得する
    def get_expenditures(self, page):
        df = []
        for dic in self.get_requests(self.url_expenditures, page):
            df.append((dic['event_date'], self.categories['expenditure'][dic['category']], dic['amount'], dic['memo']))
        df = pd.DataFrame(df, columns=['date', 'category', 'amount', 'memo'])
        df['date'] = pd.to_datetime(df['date'])
        return df
    
    # 日付指定で収入データを取得する
    def get_incomes_by_date(self, date_min, date_max):
        page_num = 1
        dfs = []
        while True:
            df = self.get_incomes(page_num)
            dfs.append(df)
            if df['date'].min() < date_min:
                break
            else:
                page_num += 1
        df = pd.concat(dfs, axis=1)
        df = df[(df['date']>=date_min)&(df['date']<date_max)].reset_index(drop=True)
        return df
    
    # 日付指定で支出データを取得する
    def get_expenditures_by_date(self, date_min, date_max):
        page_num = 1
        dfs = []
        while True:
            df = self.get_expenditures(page_num)
            dfs.append(df)
            if df['date'].min() < date_min:
                break
            else:
                page_num += 1
        df = pd.concat(dfs, axis=1)
        df = df[(df['date']>=date_min)&(df['date']<date_max)].reset_index(drop=True)
        return df
```

収入と支出のデータをpage指定・日付指定でpandasのDataFrame形式で取り出せるようにしています。他にも色々できますが、普段自分が使うのはこの２つ。日付については以下のように、指定1≦日付＜指定2で取り出せるようにしています。このほうが1か月単位の取り出しがしやすいので。使用例は以下です。

```python
# 2024年1月の支出データを取り出す例
date_min = pd.to_datetime('2024-01-01')
date_max = pd.to_datetime('2024-02-01')
sa = sumumaAPI()  
df = sa.get_expenditures_by_date(date_min, date_max)
```

# 終わりに
自分は特にcsv入出力とAPI機能に惹かれてSUMUMAを使っています、とても便利なサービスですので皆さんも是非！余談ですが先日SUMUMAで少し不具合があり、問い合わせを送ったところとても早く対応していただけました。この記事は前々から書こうと思っていた内容なのですが、放置していたのが申し訳なくなるほどに…。