您的案例有点困难,但这正是值得探索的原因。这是对问题的逐步剖析:
桌面通知对话框
首先,当我尝试在 Chrome 中运行您的测试时,“您要允许桌面通知吗?” 对话框干扰了测试(它在第二次 @ 987654323@ 这就是为什么文本框失去焦点并且其中一个条目被接受,导致无法找到其他建议的原因。
我使用这个技巧解决了这个问题:Disable Chrome notifications (Selenium)
寻找合适的容器
通过确定可以将建议的容器定位为By.xpath("(//div[@class='viewport'])[2]"),您已经走得很远了。但是,从那里开始,您需要更具体地寻找正确的子元素。此外,由于这是动态内容,建议使用显式等待语句以确保测试不会过早失败,以防元素加载时间更长。
我更改了您的测试,使其看起来是 <li> 元素,它们是 <div> 元素的子元素,具有 viewport 类。这些元素具有相应地格式化城市、机场和国家名称的子元素。要获得这些文本,您必须深入了解 DOM 结构。这是解决方案:
WebElement list = new WebDriverWait(driver, 2000).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("(//div[@class='viewport'])[2]")));
List<WebElement> elements = list.findElements(By.tagName("li"));
for (WebElement element : elements) {
String city = element.findElement(By.className("ac_cityname")).getText();
String airport = element.findElement(By.className("ac_airportname")).getText();
String country = element.findElement(By.className("ac_country")).getText();
System.out.println(city + " " + airport + " (" + country + ")");
}
到目前为止,一切都很好。但请注意,此解决方案会为您提供以下输出:
Mumbai (BOM) Chatrapati Shivaji (India)
Madras (MAA) Chennai (India)
Chennai (MAA) Chennai (India)
Madurai (IXM) (India)
()
()
()
()
()
()
滚动
这是因为您的页面的另一个特点:它只呈现实际可见元素的文本。所以除了上面的代码,应用这个技巧来确保所有元素在检索它们的文本之前都被滚动到:Scroll Element into View with Selenium
长话短说:这是我的最终版本:
driver.get("https://www.yatra.com/");// URl of yatra
String origin ="(//input[@name='flight_origin_city'])[1]";// text box for entering origin
driver.findElement(By.xpath(origin)).sendKeys("Bangalore");
String destination = "(//input[@name='flight_destination_city'])[1]";// text for entering destination
driver.findElement(By.xpath(destination)).sendKeys("M");
WebElement list = new WebDriverWait(driver, 2000).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("(//div[@class='viewport'])[2]")));
List<WebElement> elements = list.findElements(By.tagName("li"));
for (WebElement element : elements) {
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
String city = element.findElement(By.className("ac_cityname")).getText();
String airport = element.findElement(By.className("ac_airportname")).getText();
String country = element.findElement(By.className("ac_country")).getText();
System.out.println(city + " " + airport + " (" + country + ")");
}
在 Google Chrome 中运行时应该会为您提供以下输出:
Mumbai (BOM) Chatrapati Shivaji (India)
Madras (MAA) Chennai (India)
Chennai (MAA) Chennai (India)
Madurai (IXM) Madurai (India)
Mangalore (IXE) Bajpe (India)
Mysore (MYQ) Mysore (India)
Coorg (MYQ) (nearest airport Mysore) (India)
Male (MLE) Male (Maldives)
Melbourne (MEL) Tullamarine (Australia)
Mauritius (MRU) Plaisancet (Mauritius)