内容
部屋名、日付を選択すればディズニーランドホテルの予約画面まで遷移
動機
ブラウザ操作やスクレイピングに慣れたいと思っていて、せっかくするなら興味があったディズニー予約サイトでやってみようと考えた。
ディズニー予約サイトではpythonのrequestsが使えなかったため、seleniumでブラウザ操作を再現する必要があることがわかり、seleniumに慣れる良い機会だと考えた。
環境
python 3.XX
selenium
chromedriver
以上をダウンロード
部屋選択・日付入力
実際はディズニーランドホテルだけで49種類もの部屋の種類がありましたが、見やすさのため省略しています。
# 事前に部屋選択を行う処理
# 部屋の種類リスト
# 見やすさの為、一部部屋のみ
room_types = [
"スタンダード スーペリアルーム(1-3階)",
"スタンダード スーペリアルーム(3-4階)",
"スタンダード スーペリアルーム(4-9階)",
"スタンダード スーペリアルーム(パークビュー)(3-6階)",
"スタンダード スーペリアルーム(パークビュー)(7-8階)",
]
print("選択可能な部屋の種類:")
for idx, room in enumerate(room_types):
print(f"{idx+1}: {room}")
room_choice = int(input("選択する部屋の種類の番号を入力してください: "))
selected_room_type = room_types[room_choice - 1]
print(f"\n選択された部屋の種類: {selected_room_type}")
# 予約希望日(YYYYMMDD形式)を入力。
# 希望日から対象の月を算出。
desired_date = input("予約希望日(例: 20250508)を入力してください: ").strip()
try:
desired_datetime = datetime.datetime.strptime(desired_date, "%Y%m%d")
except Exception as e:
print(f"日付形式が正しくありません: {str(e)}")
sys.exit()
# 希望日から対象の月(例:"2025,5")を算出(後々必要)
selected_value = f"{desired_datetime.year},{desired_datetime.month}"
print(f"算出された対象月: {selected_value}")
実行すると
選択可能な部屋の種類:
1: スタンダード スーペリアルーム(1-3階)
2: スタンダード スーペリアルーム(3-4階)
3: スタンダード スーペリアルーム(4-9階)
4: スタンダード スーペリアルーム(パークビュー)(3-6階)
5: スタンダード スーペリアルーム(パークビュー)(7-8階)
選択する部屋の種類の番号を入力してください: 2
選択された部屋の種類: スタンダード スーペリアルーム(3-4階)
予約希望日(例: 20250508)を入力してください: 20250511
算出された対象月: 2025,5
ブラウザ操作
seleniumのversionによってはchromeのパスを通す必要があるそうです。
具体的にはselenium4.6以降の場合webdriver-managerのおかげでパスを通す必要がないらしいです。
# 以下、ChromeDriverを起動して自動操作を実施する
url = "https://reserve.tokyodisneyresort.jp/sp/hotel/search/"
chrome_options = Options()
#chrome_options.add_argument('--headless') # ヘッドレスモードを有効にする場合はコメント解除
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36')
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_experimental_option('detach', True)
driver = webdriver.Chrome(options=chrome_options)
try:
# トップページを表示
driver.get(url)
time.sleep(3) # ページロード待機
# 「ホテルから」をクリック
link = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//*[text()='ホテルから']"))
)
link.click()
# 「ホテル」をクリック(例として「東京ディズニーランド」を選択)
link = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//a[contains(., '東京ディズニーランド')]"))
)
link.click()
# XPath を動的に組み立てる(部屋の種類に合わせる)
room_xpath = (
f"//button[contains(@class, 'js-callVacancyStatusSearch') and "
f"contains(@class, '{selected_room_type}')]"
)
print("使用する XPath:", room_xpath)
room_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, room_xpath))
)
driver.execute_script("arguments[0].scrollIntoView(true);", room_button)
try:
room_button.click()
except Exception:
ActionChains(driver).move_to_element(room_button).click().perform()
# 大人の人数を選択(例:2名)
select_element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "adultNum"))
)
select_element.click()
option = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//select[@id='adultNum']/option[@value='2']"))
)
option.click()
# 「次へ」ボタンをクリック
next_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button.next.js-conditionHide"))
)
next_button.click()
# カレンダーのセレクトボックス(ID: boxCalendarSelect)から、算出された対象月をセット
select_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "boxCalendarSelect"))
)
select_box = Select(select_element)
select_box.select_by_value(selected_value)
time.sleep(3) # カレンダー更新待機
# 希望日のセルを取得してクリック(data-date属性が一致し、かつ"ok"クラス付き)
date_cell_xpath = f"//td[contains(@class, 'ok') and @data-date='{desired_date}']"
try:
date_cell = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, date_cell_xpath))
)
print(f"{desired_date} は空室があるようです。セルをクリックして詳細画面へ移行します。")
date_cell.click()
except Exception as e:
print(f"{desired_date} のセルが見つからないか、クリックできませんでした: {str(e)}")
driver.quit()
sys.exit()
# 詳細画面(予約手続きボタンが含まれる部分)の表示状態を変更
room_detail_id = f"room_{desired_date}"
driver.execute_script("document.getElementById('priceInformationList').style.display = 'block';")
room_detail = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, room_detail_id))
)
# 「予約手続きに進む」ボタンを取得しクリック(テキストに「予約手続きに進む」を含み、disableクラスがないもの)
try:
reserve_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((
By.XPATH, f"//li[starts-with(@id, 'room_{desired_date}')]" +
"//p[@class='btnReserve']/button[contains(., '予約手続きに進む') and not(contains(@class, 'disable'))]"
))
)
print("予約手続きに進むボタンが見つかりました。クリックします。")
reserve_button.click()
except Exception as e:
print(f"予約手続きに進むボタンが見つからない、またはクリックできませんでした: {str(e)}")
except Exception as e:
print(f"Error: {str(e)}")
finally:
print('exit')
実行すると
使用する XPath: //button[contains(@class, 'js-callVacancyStatusSearch') and contains(@class, 'スタンダード スーペリアルーム(3-4階)')]
20250511 は空室があるようです。セルをクリックして詳細画面へ移行します。
予約手続きに進むボタンが見つかりました。クリックします。
exit
実際に予約を自動化する場合はサイト混雑時の待機部屋対策やページ遷移時の待機時間調整も必要です。サーバーへの負荷を考えての運用も必要ですね。
何かあればご教授ください🙇