hirano00o's blog

技術的な記録、日常の記録

銀行や証券口座から入出金や株の損益を取得するライブラリを作成した

以前のブログでMoney Forward MEから脱却するためのプロセスを書いた。 hirano00o.hateblo.jp 開発を進める中でスクレイピングをして明細を取得するPythonのライブラリを公開した。 github.com

PyPiはこちら。 pypi.org

何で作成したか

いくつか個人で作成されたツールはあれど、ほとんどがCSVのファイル出力まで実装されている。現状は取得したデータはBigQueryに挿入するので、ファイル出力までされた場合、ファイルを読み込んで整形する手間が増える。そのため、データの取得までを行うライブラリを作成した。

何ができるか

銀行と証券口座、WealthNaviに対して残高や入出金履歴、保有株や投資信託の数や取得単価などが取得できる。

銀行

  • 残高の取得
  • 入出金履歴の取得

残高は複数の口座を持てる銀行もあるため、口座番号ごとに残高が取得できるように作成している。入出金に関しては、指定した期間と口座番号に対する履歴が取得できる。期間を指定しない場合は、銀行の入出金ページを開いたときに出力される期間のデータが返される(つまりデフォルトの期間は銀行によりけり)。

証券

  • 保有株数、取得単価、現在値の取得
    • 米国株含む
  • 投資信託の保有口数、取得単価、基準価額の取得
    • NISA、旧NISA含む

基本的には最小限しか取得していない。例えば損益は、株数 * (現在値 - 取得単価)で、前日比なども継続して取得していれば算出できる。 そのため、現在値の推移や損益推移を知りたい場合は、継続してデータを取得、保存しておく必要がある。

米国株やETFは、円に直さずドルのままデータを返すため、円で値を知りたい場合は、別途為替レートが必要となる。例えば外為オンラインでは、登録不要でレートがJSON形式で取得できる。

WealthNavi

  • 資産クラス、現在価格、損益の取得

WealthNaviは証券口座とは異なり、取得単価や保有数が不明なため、各資産クラスの現在価格と損益をそのまま取得している。WealthNavi上では、ドルでも損益等が見られるが、基本的に入出金は円なので、円でデータを返す。

どの金融機関に対応しているか

現在は下記の金融機関に対応している。

  • 銀行
    • みずほ銀行
    • SBIネット銀行
  • 証券
    • SBI証券
  • その他
    • WealthNavi

WealthNaviは、2段階認証をしているユーザが多いと思う。設定を変更せずに利用できるよう、TOTPのコードを入れればログインできるようにしている。

構成と実装

クラスの構造は 各金融機関のクラス < Bank or Securitiesクラス < Baseクラスの3段階になっており、共通して利用する関数は可能な限り上のクラスにまとめている。例えば、ロード待ちをする関数は全体で使うので Baseクラス、残高を取得する関数は銀行全体で利用するので、abstractmethodBankクラスに定義、実装は各銀行用のクラスで行っている。

スクレイピングは定番のseleniumbeautifulsouppandasを利用している。SBIネット銀行はJSが大量に利用されているのでかなり苦労した。ローカルで動かす場合とKuberenetes on RaspberryPi5で動かす場合では、seleniumがエラーを出力する箇所が異なり、スクショを見てはどこで操作ができなくなったかを確認し、JSのロード待機させたりと調整をした。 例えば入出金履歴の期間を設定する際、月や日付などをマウスでクリックするが、リストがゆっくりとアニメーションで出てくるため、動作させるスペックによって出てくるまでの時間が異なる。今のところはクリックしてからsleepで待機しているが、できれば別の方法で解決していきたい。

使い方

WebDriverと口座の情報を準備すれば利用できる。WebDriverは、ChromeとFirefoxがよく使われるが、ここではFirefoxを例にとる。

あらかじめ firefox-esr(もしくはfirefox)をインストールし、geckodriverをダウンロードしておく必要がある。

# Apple SiliconのMacの場合
# brew install --cask firefox
apt install -y firefox-esr

# Apple SiliconのMacの場合
# https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-macos-aarch64.tar.gz
wget -qO /tmp/geckodriver.tar.gz \
    "https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-linux-aarch64.tar.gz" \
    && tar -xzf /tmp/geckodriver.tar.gz -C /usr/local/bin/ \
    && rm /tmp/geckodriver.tar.gz

準備ができたら下記のスクリプトを作成して実行する。ユーザIDとパスワード、firefoxのバイナリは各自の環境に合わせて変更する。

from selenium import webdriver
from datetime import timedelta, datetime
from zoneinfo import ZoneInfo

from acctf.bank.sbi import SBI

user_id = "" # ユーザIDを入れる
password = "" # パスワードを入れる
start_date = datetime.now(ZoneInfo("Asia/Tokyo")).date() - timedelta(days=7)
end_date = datetime.now(ZoneInfo("Asia/Tokyo")).date() - timedelta(days=1)


def create_driver() -> webdriver:
    options = webdriver.FirefoxOptions()
    options.add_argument("-headless")
    options.binary_location = "/usr/bin/firefox-esr" # firefoxの場所はwhich firefoxで調べて適宜変更
    service = webdriver.FirefoxService(executable_path="/usr/local/bin/geckodriver")
    driver = webdriver.Firefox(service=service, options=options)

    return driver

s = SBI(create_driver()).login(user_id, password)
hist = s.get_transaction_history(
    account_number="", start=start_date, end=end_date
)
print(f"日付, 取引内容, 金額")
for h in hist:
  print(f"{h.date}, {h.content}, {h.value}")

s.logout()
s.close()

実行すると下記のように出力される。日付はdatetime.dateなのでデータを取得した後に何か操作する場合でも加工しやすい。

日付, 取引内容, 金額
2023-12-01, ATM引き出し, -10000.0
2024-12-20, 給与, 200000.0

終わりに

今回は銀行や証券口座のデータを取得するライブラリを作成した。利用する際は、金融機関に迷惑がかからないよう、口座がロックされないように注意してください。

本ライブラリは、まだまだ対応していない金融機関や機能が多い。対応してほしい機能や修正したい箇所などがあれば、IssueやPullRequestを作成頂けると幸いです。