PythonとSeleniumを使って三菱UFJ銀行の明細取得（CSVダウンロード）する

PythonとSeleniumを使って、三菱UFJ銀行サイトにログインして明細データを取得（CSVダウンロード）する方法を解説します。サンプルコード全文も記事の後半に載せているので参考になれば幸いです。

※2021/04/04時点の情報です。

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## はじめに
ログインまでの部分や、webdriverのプロファイル設定に関する部分については、以下記事をご確認ください。

https://qiita.com/yoshi2045/items/765c589ce0c02e9d888d

↑ログインするところまでのサンプルです。（本記事のサンプルコードにもログイン部分あります）

https://qiita.com/yoshi2045/items/be739680bceb2f2df6a2

↑サンプルのwebdriverは、Firefoxを使っています。CSVダウンロードするにあたって、Firefoxのプロファイル設定が必要なので、そのあたりを解説しています。

## 対象画面まで遷移させる

まず、三菱UFJ銀行のログイン後のTOP画面から明細ダウンロード画面までどういう経路で遷移できるかを確認してみます。

＜画面フロー＞

1. TOP画面
2. 入出金画面
3. 明細ダウンロード画面

上記フローで目的の画面まで遷移できることが分かりました。

では続いて、具体的に各画面ごとの遷移処理を見ていきましょう。

◆ログイン後のTOP画面

![20210404-001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/8e1e2dd3-3315-8ede-77f5-efd07e2a3409.png)

TOP画面から入出金明細画面への遷移は、「入出金明細」をクリックします。この要素にはIDや使えそうなclass指定がなかったので、XPATH指定で要素を特定しました。

```python

# 入出金明細画面へ遷移
browser.find_element_by_xpath("//p[contains(.,'入出金明細')]").click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.XPATH, "//img[@alt='明細をダウンロード']"))
)
```

また、次画面の要素が表示されるまでWebDriverWait()を使って待機させています。

◆入出金明細画面

![20210404-002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/45f6c081-0a68-34e4-7575-28ccc931d997.png)

入出金明細画面の明細行部分の最後に「明細をダウンロード」ボタンがあるのでこの要素を指定します。

```python
# 明細ダウンロード画面へ遷移
browser.find_element_by_xpath("//img[@alt='明細をダウンロード']").click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "appoint"))
)
```



◆明細ダウンロード画面

![20210404-003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/4e1352f0-57e8-711b-cbe0-0d3fd33f0f61.png)

明細ダウンロード画面に遷移できました。

## 期間を指定してダウンロード実行

続けて明細ダウンロード画面上にある、照会期間を設定していきます。

まずは取得対象をラジオボタンで選択する必要がありますが、今回のサンプルでは期間を指定して取得すたいため、「期間指定」を選択します。

```python

# ラジオボタン指定
browser.find_element_by_id("appoint").click()
```
ラジオボタンの選択は、finde_element系のメソッドで要素を特定し、click()で実現可能です。

続いて期間の選択ですが、三菱UFJ銀行の場合は開始、終了の年月日がすべてドロップダウンになっています。ドロップダウンの要素を指定するには、Select()を使用します。

そのため最初にSelectオブジェクトをimportしておきます。

```python
from selenium.webdriver.support.select import Select
```

ドロップダウン要素の選択の仕方は次のとおりです。

```python
# ダウンロード対象期間指定
dropdown = browser.find_element_by_id("year_01")
select = Select(dropdown)
select.select_by_visible_text("2021")
```

select_byの仕方は、上記のようにテキストの値を指定する方法のほか、インデックスやvalueの値で特定することも可能です。

以下の記事が参考になりました。

[【Selenium】ドロップダウン/selectタグ選択,取得方法まとめ | ゆうきのせかい
](https://yuki.world/selenium-select/)

今回のようなケースでは、取得したい期間の日付＝表示テキストの値なので、select_by_visible_text()が一番適していると思います。

最後に、「ダウンロード（CSV形式）」の要素をXPATHで指定してクリックすると、ファイルがダウンロードできます。

```python
# CSVダウンロードボタンクリック
browser.find_element_by_xpath("//div[@id='contents']/div[2]/div/button/img").click()
```

以上、PythonとSeleniumを使って三菱UFJ銀行の明細取得（CSVダウンロード）する方法でした！

## サンプルコード全文
設定ファイル（login_info.json）の解説は、[こちらの記事](https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104#%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E6%83%85%E5%A0%B1%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)を参照ください。

```python
#
# 三菱UFJ銀行サイトへログイン＆CSVダウンロード
#

import json
from selenium import webdriver
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.select import Select

# 設定ファイルからログイン情報を取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "bank_ufj_biz"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# ダウンロードフォルダ
# 相対パス指定はできない模様
# dl_folder = r"..\dl-data"
dl_folder = r"ダウンロードフォルダのパスを指定"

# オプション設定
options = FirefoxOptions()

# ヘッドレスモードを有効にする
options.add_argument('--headless')

# プロファイル設定
fp = webdriver.FirefoxProfile()

# ダウンロードフォルダ指定
# 0: デスクトップ、1:システム規定のフォルダ、2:任意の指定フォルダ
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.dir", dl_folder)

# ダウンロードマネージャウィンドウを表示させない
fp.set_preference("browser.download.manager.showWhenStarting", False)

# MIMEタイプを設定
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream;text/csv")

# Firefoxを起動する
browser = Firefox(options=options, firefox_profile=fp)

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("tx-contract-number")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("tx-ib-password")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_class_name("gonext")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "md-allmenu"))
)

# 入出金明細画面へ遷移
browser.find_element_by_xpath("//p[contains(.,'入出金明細')]").click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.XPATH, "//img[@alt='明細をダウンロード']"))
)

# 明細ダウンロード画面へ遷移
browser.find_element_by_xpath("//img[@alt='明細をダウンロード']").click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "appoint"))
)

# 照会期間指定
# ラジオボタン指定
browser.find_element_by_id("appoint").click()

# ダウンロード対象期間指定
# TODO:設定値は可変でセットできるようにしたほうがよい
# From
dropdown = browser.find_element_by_id("year_01")
select = Select(dropdown)
select.select_by_visible_text("2021")
dropdown = browser.find_element_by_id("month_01")
select = Select(dropdown)
select.select_by_visible_text("3")
dropdown = browser.find_element_by_id("day_01")
select = Select(dropdown)
select.select_by_visible_text("1")

# To
dropdown = browser.find_element_by_id("year_02")
select = Select(dropdown)
select.select_by_visible_text("2021")
dropdown = browser.find_element_by_id("month_02")
select = Select(dropdown)
select.select_by_visible_text("3")
dropdown = browser.find_element_by_id("day_02")
select = Select(dropdown)
select.select_by_visible_text("31")

# CSVダウンロードボタンクリック
browser.find_element_by_xpath("//div[@id='contents']/div[2]/div/button/img").click()

# ログアウト
browser.find_element_by_link_text("ログアウト").click()

# 処理終了
browser.quit()
```