如何在不使用for循环</webelement>的情况下转储<webelement>列表的内容

时间:2015-02-15 23:58:10

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

我正在尝试使用for循环将列表的内容写入文件。是否可以使用一个语句转储列表的全部内容?目前它很慢。我想加快这个计划。

By getChanges = By.xpath("//td[contains(@class,'blob-code blob-code-addition') or contains(@class,'blob-code blob-code-deletion')]");

List<WebElement> listChanges = driver.findElements(getChanges);

for (int count = 0; count < listChanges.size(); count++) {

    String codeChanges=driver.findElements(getChanges).get(count).getText();

    outputHandle.write(codeChanges);
}

要添加更多详细信息,请访问此页https://github.com/SunriseSoftVN/qlkh/commit/a8b1c3a241ccf83f33819f4b04a8d647238bdaf8#diff-33c32c1890dcfb06827b5db4bee85959

ListChanges的大小是:3408并且它会像永远一样卡在那里......我的意思是它需要花费很多时间..它不会进入无限循环,因为文件正在按预期正确写入。

添加更多代码以显示正在使用的两个级联for循环。外部循环在第二次迭代中失败,错误是页面上的内容已经更改,即使它没有。只有当我用listChanges替换对findElements的调用时才会发生这种情况。

By getCommitList = By.xpath("//a[contains(@class,'sha button-outline')]");

                List<WebElement> commitList = driver.findElements(getCommitList);

//              System.out.println("ListChanges size is :" + commitList.size());

                for(int commitCount = 0; commitCount < commitList.size(); commitCount++)
                {
                    String commitName=driver.findElements(getCommitList).get(commitCount).getText(); //works but redundant call

//                  String commitName=commitList.get(commitCount).getText();

                    System.out.println(commitName);

//                  commitList.get(commitCount).click();  //suggested improvement but fails

                    driver.findElements(getCommitList).get(commitCount).click();

                    By getChanges = By.xpath("//td[contains(@class,'blob-code blob-code-addition') or contains(@class,'blob-code blob-code-deletion')]");

                    List<WebElement> listChanges = driver.findElements(getChanges);

                System.out.println("ListChanges size is :" + listChanges.size());

                    for (int count = 0; count < listChanges.size(); count++) {

//                      System.out.println(driver.findElements(getChanges).get(count).getText());  //prints all the code changes associated with each commit

//                      String codeChanges=driver.findElements(getChanges).get(count).getText();

                        String codeChanges=listChanges.get(count).getText();

//                      System.out.println("Writing code changes into file now *********");

                        outputHandle.write(codeChanges);

                        outputHandle.write("\n");

                    }
                    //AFTER FINISHING FIRST COMMIT, YOU MOVE TO THE NEXT COMMIT ON PREVIOUS PAGE

                    driver.navigate().back();

添加以下错误消息:

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 14 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html

3 个答案:

答案 0 :(得分:1)

目前,您的代码执行此操作:

  • 查找所有元素
  • 再次查找所有元素
  • 写第一个元素
  • 再次查找所有元素
  • 写第二个元素
  • 再次查找所有元素
  • 写第三个元素
  • ...等

String codeChanges=driver.findElements(getChanges).get(count).getText();
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

看到driver.findElements的来电?每次绕循环找到所有元素。

您可能希望将其替换为listChanges,以使用您之前执行的搜索结果。

答案 1 :(得分:1)

我同意@immibis。就像我在Chrome

上对以下更改测试代码一样
By getChanges = By.xpath("//td[contains(@class,'blob-code blob-code-addition') or contains(@class,'blob-code blob-code-deletion')]");

List<WebElement> listChanges = driver.findElements(getChanges);

for (int count = 0; count < listChanges.size(); count++) {

  String codeChanges = listChanges.get(count).getText();

  System.out.println(codeChanges);
}

enter image description here

答案 2 :(得分:0)

在每次迭代中,您将导航到单个提交列表。进入该提交列表页面后,您将遍历该列表中的所有提交详细信息。

您无法将提交列表组缓存到变量,因为您在每次迭代时都会从页面导航。但是,您不需要每次都查找整个链接组。您只需要查找您要点击的列表链接。

String listSearchXPath = "//a[contains(@class,'sha button-outline')]";

// Count how many commit lists we need to lookup
int commitListSize = driver.findElements(By.xpath(listSearchXPath)).size()
System.out.println("ListChanges size is :" + commitListSize);

for(int commitCount = 0; commitCount < commitListSize; commitCount++)
    {
        // Lookup the link we're going to click on by adding an  
        // XPath index filter for the current iteration
        WebElement linkToClick = driver.findElement(By.xpath(listSearchXPath + "[" + commitCount.ToString + "]"));

        System.out.println(linkToClick.getText());

        // Click on the link. We're navigating to a new page
        // so we cannot reference this element again.
        linkToClick.click();

        // Do a new search for the details in the commit list
        List<WebElement> listChanges = driver.findElements(By.xpath("//td[contains(@class,'blob-code blob-code-addition') or contains(@class,'blob-code blob-code-deletion')]"));

        System.out.println("ListChanges size is :" + listChanges.size());

        // Iterate through the details and log to a file
        for (int count = 0; count < listChanges.size(); count++) {

            // We're still on the same page so we can reference our saved element
            // instead of doing a new search.
            String codeChanges = listChanges.get(count).getText();

            outputHandle.write(codeChanges + "\n");
    }

    //AFTER FINISHING FIRST COMMIT, YOU MOVE TO THE NEXT COMMIT ON PREVIOUS PAGE
    driver.navigate().back();
}