PythonとSeleniumを使用したASPのDatepickerコントロールの取得と自動化

この記事はPython3.6.0とSelenium3.4.0(WebDriverはGoogleChrome)を使用しております。

ASPで作成されたDatepickerコントロール(ドロップダウンカレンダー)の取得方法で苦労しましたのでメモを残します。

# DatepickerコントロールはTable
Datepickerコントロールはクリックするとカレンダーがドロップダウンされるコントロールです。
ドロップダウンされたコントロールをGoogleChromeで検証するとTableタグで構成されているのが分かりました。
よって次の様な順番で取得できます。
1. Datepickerコントロールをクリックする
2. 生成されたカレンダーTableタグを取得する
3. やりたい事をする

# 年月日を指定して自動的日付を取得するサンプル
希望の年月日を指定すると該当の日付がクリックされる関数を作ってみました。

``` DatepickerMove.py

# browserにはDatepickerコントロールがあるページが取得されている変数を渡す
# 関数を実行する前にはDatepickerコントロールがクリックされている状態とする

def DatepickerMove(browser, year, month, day):
    # タイトルをクリックして年月選択画面にする
    calendar_title = browser.find_element_by_id('CalendarExtender1_title')
    calendar_title.click()

    calendar_prev = browser.find_element_by_id('CalendarExtender1_prevArrow')
    calendar_next = browser.find_element_by_id('CalendarExtender1_nextArrow')

    time.sleep(1)
    # 年度をチェックする。違えば大小によって該当の方向へ動かす
    # 暴走した場合に備えループには制限をかける
    limit_count = 100
    for i in range(limit_count):
        if calendar_title.text == year:
            break
        elif calendar_title.text > year:
            calendar_prev.click()
        elif calendar_title.text < year:
            calendar_next.click()
    else:
        print('規定の処理回数をオーバーしました')
        return

    time.sleep(1)

    # 月度の取得を行う
    month_title = year + '年' + month + '月'
    calendar_month = browser.find_element_by_xpath('//div[@title=\"' + month_title + '\"]')
    calendar_month.click()

    time.sleep(1)

    # 日付の取得を行う
    day_title = month_title + day + '日'
    calendar_day = browser.find_element_by_xpath('//div[@title=\"' + day_title + '\"]')
    calendar_day.click()

    time.sleep(1)

```

## 何故タイトルをクリックしているのか
``` DatepickerMove.py

browser.find_element_by_id('CalendarExtender1_title')
calendar_title.click()

calendar_prev = browser.find_element_by_id('CalendarExtender1_prevArrow')
calendar_next = browser.find_element_by_id('CalendarExtender1_nextArrow')

``` 

Datepickerコントロールをクリックすると年月日に対応したカレンダー(すなわち普通のカレンダー)が生成されます。
そのタイトル(例えば"4月, 2017"と書いてある部分)をクリックすると、
今度は年月日ではなく年と1月～12月が選択出来る状態に変化します。
1月～12月の配置は日付と違い12個のボタン、並びが決まっており扱いやすい為、
一度年月の状態に変化さています。

また、クリックすると前年と翌年に移動するエレメントも取得しています。

## 何故年度を選択するのに前年と翌年をクリックさせるのか
``` DatepickerMove.py

    limit_count = 100
    for i in range(limit_count):
        if calendar_title.text == year:
            break
        elif calendar_title.text > year:
            calendar_prev.click()
        elif calendar_title.text < year:
            calendar_next.click()
    else:
        print('規定の処理回数をオーバーしました')
        return

```

前述と同様にタイトルをクリックすれば今度は年が選択出来る状態に変化します。
しかし、現在年によって年の配置が変わる為、1年ごとループさせてチェックする方法にした方が無難だと思いましたのでそこまで考えませんでした。

## 何故XPathでtitleから取得しているのか
``` DatepickerMove.py

    # 月度の取得を行う
    month_title = year + '年' + month + '月'
    calendar_month = browser.find_element_by_xpath('//div[@title=\"' + month_title + '\"]')
    calendar_month.click()

    time.sleep(1)

    # 日付の取得を行う
    day_title = month_title + day + '日'
    calendar_day = browser.find_element_by_xpath('//div[@title=\"' + day_title + '\"]')
    calendar_day.click()

```

日付の場合、暦によっては前月の日付を選択されてしまう事があります。
例えば2017年3月25日を取得しようとしてテキストで25と指定すると2017年2月25日を取得してしまいます。
よってtitleで完全な名前の状態で選択した方が無難だと思いましたのでこうしました。

# おわりに
Pythonを学び初めて1ヶ月も経っておりませんのでコーディングがアレかもしれません。
でも、浅い経験値でも簡単に色々出来る楽しい言語ですね。