You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium Java日历日期元素选择失败问题求助

Selenium(Java)日期选择问题排查与修复

我正在学习Selenium(Java),尝试在旅行页面选择3月26日,但自动化操作大多失败:要么跳转到下月日历且未选中日期,偶尔停留在3月但仍无法选中目标日期。我原本通过while循环切换到3月视图,再遍历日期元素选择26日,以下是我的代码:

public class path2usacalendar_new {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub

        System.setProperty("webdriver.chrome.driver", "/Users/DDD/WebDrivers/chromedriver");

        WebDriver driver = new ChromeDriver();

        driver.get("https://www.path2usa.com/travel-companion"); 

        driver.manage().window().maximize();
        // Scroll the Page
        JavascriptExecutor js = (JavascriptExecutor)driver;
        js.executeScript("window.scrollBy(0,1100)");

        // Click on the Date field
        Thread.sleep(3000);

        WebElement Date = driver.findElement(By.xpath("//*[@id='form-field-travel_comp_date']"));
        // js.executeScript("arguments[0].scrollIntoView(true);", Date);
        Date.click();
        //WebElement month = driver.findElement(By.xpath("//div[@class='flatpickr-month']"));
        while(!driver.findElement(By.xpath("//div[@class='flatpickr-month']")).getText().contains("March"))
        {
            Thread.sleep(2000);
            driver.findElement(By.xpath("//span[@class='flatpickr-next-month']")).click();
        }


        int count= driver.findElements(By.xpath("//span[@class='flatpickr-day ']")).size();


        for(int i=0;i<count;i++)
        {
            Thread.sleep(2000);
            String text=driver.findElements(By.xpath("//span[@class='flatpickr-day ']")).get(i).getText();
            if(text.equalsIgnoreCase("26"))
            {
                // driver.findElements(By.cssSelector("td[class*='day']")).get(i).click();
                driver.findElements(By.xpath("//span[@class='flatpickr-day ']")).get(i).click();
                System.out.println("The select day is:"+text);
                break;
            }
        }
        String date = driver.findElement(By.xpath("//*[@id='form-field-travel_comp_date']")).getAttribute("value");
        System.out.println("The select date is:"+date);

    }

}

问题排查与修复方案

  1. 硬编码等待不可靠:多个Thread.sleep()会因页面加载速度波动导致元素未就绪就执行操作,这是核心问题。改用Selenium显式等待替代。
  2. 月份定位不准确://div[@class='flatpickr-month']可能匹配左右两个月份面板,导致判断逻辑混乱,需定位当前激活的月份标题。
  3. 日期元素XPath有空格://span[@class='flatpickr-day ']末尾的空格会导致匹配失败,且未过滤不可点击的禁用日期。
  4. 重复查找元素低效:循环内反复调用findElements()易引发元素过时异常,应提前缓存元素列表。

修改后的稳定代码

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.List;

public class path2usacalendar_new {

    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "/Users/DDD/WebDrivers/chromedriver");
        WebDriver driver = new ChromeDriver();
        driver.get("https://www.path2usa.com/travel-companion"); 
        driver.manage().window().maximize();
        
        // 初始化10秒超时的显式等待
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        
        // 滚动到日期字段(确保元素存在后再滚动)
        WebElement dateField = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("form-field-travel_comp_date")));
        ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", dateField);
        
        // 点击打开日历
        wait.until(ExpectedConditions.elementToBeClickable(dateField)).click();
        
        // 切换到3月视图:定位当前激活的月份标题,避免多面板干扰
        WebElement currentMonth = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".flatpickr-current-month")));
        while (!currentMonth.getText().contains("March")) {
            WebElement nextBtn = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(".flatpickr-next-month")));
            nextBtn.click();
            // 更新当前月份元素引用
            currentMonth = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".flatpickr-current-month")));
        }
        
        // 获取所有可点击的3月日期(过滤禁用日期)
        List<WebElement> availableDates = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector(".flatpickr-day:not(.disabled)")));
        
        // 查找并点击26日
        for (WebElement date : availableDates) {
            if (date.getText().equals("26")) {
                wait.until(ExpectedConditions.elementToBeClickable(date)).click();
                System.out.println("选中的日期是: " + date.getText());
                break;
            }
        }
        
        // 验证输入框中的日期值
        String selectedDate = dateField.getAttribute("value");
        System.out.println("输入框中的日期值: " + selectedDate);
        
        // 关闭浏览器释放资源
        driver.quit();
    }
}

关键改进点

  • 用WebDriverWait替代所有Thread.sleep(),确保元素就绪后再执行操作,大幅提升稳定性。
  • 使用CSS选择器精准定位:.flatpickr-current-month定位当前激活月份,.flatpickr-day:not(.disabled)过滤不可点击的日期。
  • 提前缓存日期元素列表,避免重复查找引发的元素过时异常。
  • 新增driver.quit()关闭浏览器,释放系统资源。

内容的提问来源于stack exchange,提问作者Nik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:10:23