【问题标题】:Loop through page links in div and click each link containing a specific value in Selenium (java)遍历 div 中的页面链接,然后单击包含 Selenium (java) 中特定值的每个链接
【发布时间】:2020-10-02 19:35:39
【问题描述】:

我有一个 html 页面,其中的部分结构如下:

<section id="fl-results" class="fl-results-revenue">
	<li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
		<a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-1" tabindex="-1" id="ui-id-3">Details</a>
	</li>
	<!-- Some html -->
	<li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
		<a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-2" tabindex="-1" id="ui-id-5">Details</a>
	</li>
	<!-- Some html -->
	<li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
		<a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-3" tabindex="-1" id="ui-id-8">Details</a>
	</li>
	<!-- Some html -->
	<li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
		<a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-4" tabindex="-1" id="ui-id-19">Details</a>
	</li>
</section>

现在我想单击带有 id fl-results 部分的所有链接以获取详细信息。 在我的代码中,我等待元素可点击,这正在工作,然后尝试全部点击:

wait.until(ExpectedConditions.elementToBeClickable(By.className("toggle-flight-block-details")));

当我尝试下面的代码时,它只会打开第一次出现的链接:

driver.findElement(By.className("toggle-flight-block-details")).click();

我看到一个帖子建议使用 cssSelector

driver.findElement(By.cssSelector("a[href*='flight-details-1']")).click();

这需要我遍历所有具有此类的链接。迭代有效,但点击给我一个错误

//loop through page and click all link details
List<WebElement> allLinksWebpage = driver.findElements(By.className(waitCondition));
int k = allLinksWebpage.size();
for(int i=0;i<k;i++)
{
    if(allLinksWebpage.get(i).getAttribute("href").contains("flight-details"))
    {
        String waitCondition = "flight-details-"+(i+1);
        String link = allLinksWebpage.get(i).getAttribute("href");
        driver.findElement(By.cssSelector("a[href*='"+waitCondition+"']")).click();
    }
}

给出的错误是:

线程“main”中的异常 org.openqa.selenium.ElementClickInterceptedException:元素点击 截获:元素 ... 在点 (392, 730)。其他元素会收到点击:...

我看到了一个关于类似错误的post,它说要改用javascript,因为它与chrome有关,但我不知道如何在我的情况下实现它?

我正在使用谷歌浏览器驱动程序版本 83.0.4103.97。

我正在查看的 HTML 页面是来自 United Airline 的航班搜索结果

【问题讨论】:

    标签: java selenium selenium-webdriver web-scraping selenium-chromedriver


    【解决方案1】:

    代替这一行:

    List<WebElement> allLinksWebpage = driver.findElements(By.className(waitCondition));
    

    #在此处更新

    另一种方法使用这个css选择器:section#fl-results li a.toggle-flight-block-details,使用.visibilityOfAllElementsLocatedBy将它们收集到一个等待列表中。

    for each提取:

    WebDriverWait wait = new WebDriverWait(driver, 20);
    //update here
    List<WebElement> allLinksWebpage = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("section#fl-results li a.toggle-flight-block-details")));
    for(WebElement element: allLinksWebpage) {
        if(element.getAttribute("href").contains("flight-details")) {
            ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
            wait.until(ExpectedConditions.elementToBeClickable(element));
            ((JavascriptExecutor) driver).executeScript("arguments[0].click();", element);
        }
    }
    

    见上文如何使用JavascriptExecutor实现arguments[0].click();

    您需要以下导入:

    import org.openqa.selenium.JavascriptExecutor;
    

    但我想每次点击Details链接,都会出现详细信息并使页面结构发生变化,所以下一个Details到底部,点击之前放这个参数arguments[0].scrollIntoView(true);

    【讨论】:

    • 嗨,答案看起来很有趣。但是尝试了它,它仍然给我错误:预期条件失败:等待 By.cssSelector 定位的所有元素的可见性:section#fl-results > li > a。请参阅错误详细信息here。我正在查看的 html 页面是来自 United Airline 的航班搜索结果
    • @gunner 你错误地显示了问题中的 HTML 结构,与原始页面不同,sectionli 之间还有其他标签,因此之前的 ccs 选择器将不起作用。我更新了答案,将 CSS 选择器 section#fl-results &gt; li &gt; a 更改为 section#fl-results li a.toggle-flight-block-details。希望这会有所帮助。
    【解决方案2】:

    您可以使用section web 元素获取所有包含类名toggle-flight-block-details 的web 元素;

    WebElement section = driver.findElement(By.id("fl-results"));
    List<WebElement> detailsList = section.findElements(By.className("toggle-flight-block-details"));
    

    然后你可以遍历detailsList并使用JavascriptExecutor点击它们

    JavascriptExecutor js = (JavascriptExecutor) driver;
    for (int i = 0; i <detailsList.size(); i++) {
        js.executeScript("arguments[0].click();", detailsList.get(i));
    }
    

    【讨论】:

    • 谢谢,这行得通。起初它不是,我意识到因为detailsList.size() 是0。所以我添加了等待条件wait.until(ExpectedConditions.elementToBeClickable(By.className("toggle-flight-block-details")));,它工作得很好!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多