如何用Python Selenium在指定网站日历中选择日期?
Hey Alan, let's fix that date selection part of your Selenium script! The issue with your current XPath is that it relies on hard-coded indexes (like div[5]) which will break if the month's date layout changes, and the text matching isn't robust enough. Here's how to solve this:
First, Understand the Calendar Date Elements
First, use your browser's DevTools to inspect the date buttons in the calendar. You'll notice that:
- Valid (current month) dates are usually enabled (no
disabledattribute or class) - Each date button has the day number as its text (might have extra whitespace, so we'll handle that)
Fix the Date Selection XPath
Instead of hard-coding positions, use a flexible XPath that targets the exact day text and ensures the date is clickable:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # ... your existing code up to the month/year selection ... # Add this part to select the target day (make sure your keys dict has a "day" field, e.g., "day": "20") target_day = k["day"] # Wait for the calendar days grid to load (more reliable than time.sleep) WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'calendar-days')]")) ) # XPath to find the enabled button with the target day text (normalizing whitespace) date_xpath = f"//button[normalize-space(text())='{target_day}' and not(@disabled)]" # Wait for the date button to be clickable, then click it WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, date_xpath)) ).click()
Key Improvements:
- Flexible XPath: No hard-coded indexes, so it works for any month layout
- Normalized Text:
normalize-space()handles any extra spaces in the button text - Enabled Check:
not(@disabled)ensures you don't try to click grayed-out past/future month dates - Explicit Waits: Replaces
time.sleepwithWebDriverWaitto make the script more stable (waits until elements are ready instead of arbitrary delays)
Updated Full Script
Here's your full script with the fixes included:
from selenium import webdriver from config import keys from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By def order(k): chr_options = Options() chr_options.add_experimental_option("detach", True) driver = webdriver.Chrome('./chromedriver', options=chr_options) driver.get(k['website_url']) # Wait for the Date button to be clickable WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/section/div/div/div/div[1]/div/div[2]/div/div/div[3]/div/div[2]/button')) ).click() # Select target month/year while True: text = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, '//*[@id="app-body"]/div[2]/div[2]/div[1]/div[2]/div[1]/div/p')) ).get_attribute('innerText') if text == k["month_year"]: break else: WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, '//*[@id="app-body"]/div[2]/div[2]/div[1]/div[2]/div[1]/button[2]/span[1]/span')) ).click() # Select target day target_day = k["day"] WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'calendar-days')]")) ) date_xpath = f"//button[normalize-space(text())='{target_day}' and not(@disabled)]" WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, date_xpath)) ).click() if __name__ == '__main__': order(keys)
Notes:
- Make sure your
keysdictionary includes a"day"key with the target day as a string (e.g.,"day": "20"). - If the calendar uses a different class for disabled dates (like
class="disabled-day"), adjust the XPath tonot(contains(@class, 'disabled-day'))instead ofnot(@disabled).
内容的提问来源于stack exchange,提问作者Alan Chen
相关产品推荐
相关产品推荐

