【问题标题】:Selenium/Python: How do I move to a new window with no window name given?Selenium/Python:如何在没有给出窗口名称的情况下移动到新窗口?
【发布时间】:2016-12-05 22:04:33
【问题描述】:

我需要切换到单击链接后打开的新窗口。我没有窗口名称,也没有链接中的目标,因此 move_to.window() 会引发异常。如何切换到新窗口?

编辑:我正在使用 driver.switch_to.window() 来获取窗口句柄列表的最后一个索引。 Selenium 似乎正在抓住另一个窗口并执行以下第一个操作,即从下拉列表中选择一个选项。然而,在选择该项目后,立即抛出 NoSuchElementException ,说明我刚刚对其执行操作的元素无法定位。这是我的 Python 代码:

    driver.find_element_by_xpath("//a[@href=\"link_that_opens_other_window\"]").click()

    Select(driver.find_element_by_id("programID")).select_by_value("621")

    driver.find_element_by_xpath("//a[contains(., \"New Schedule Wizard\")]").click()

    config.long_rest() # short_rest() and long_rest() are custom functions I defined to wait for pages to load

    driver.switch_to.window(driver.window_handles[-1])

    config.short_rest()

    # In newly opened window, import old rotations
    Select(driver.find_element_by_xpath("//select[@name = \"rotationsetID\"]")).select_by_value("16")
    Select(driver.find_element_by_xpath("//select[@name = \"scheduleID\"]")).select_by_index(1)
    driver.find_element_by_xpath("//input[@value=\"Next Step >\"]").click()

我得到的错误是:

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//select[@name = "rotationsetID"]"}
(Session info: chrome=54.0.2840.99)
(Driver info: chromedriver=2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed),platform=Windows NT 6.1.7601 SP1 x86_64)

我也尝试将新窗口视为框架,但这也没有奏效。

编辑:我尝试过的最新代码:

    driver.find_element_by_xpath("//a[@href=\"link_that_opens_other_window\"]").click()

    Select(driver.find_element_by_id("programID")).select_by_value("621")

    driver.find_element_by_xpath("//a[contains(., \"New Schedule Wizard\")]").click()

    config.long_rest() # short_rest() and long_rest() are just custom functions I defined to wait for pages to load

    old_window = driver.window_handles[0]
    new_window = driver.window_handles[-1]

    print "Old: ", type(old_window), old_window
    print "New: ", type(new_window), new_window

    driver.switch_to.window(new_window)

    print "Current window: ", driver.current_window_handle # this line prints out the same value as new_window

    config.short_rest()

    # In newly opened window, import old rotations
    Select(driver.find_element_by_name("rotationsetID")).select_by_value("16")
    Select(driver.find_element_by_xpath("//select[@name = \"scheduleID\"]")).select_by_index(1)
    driver.find_element_by_xpath("//input[@value=\"Next Step >\"]").click()

编辑:这是我要抓取的元素的 HTML 代码:

<table cellspacing="8" cellpadding="0" border="0">
  <tbody>
    <tr>
      <td>Academic Year:  </td>
      <td>
        <select name="rotationsetID" onchange="selectAcYearSchedule(this);">
          <option value="0">(select academic year)</option>
          <option value="13">July 1, 2013 - June 30, 2014</option>
          <option value="14">July 1, 2014 - June 30, 2015</option>
          <option value="15">July 1, 2015 - June 30, 2016</option>
          <option value="16">July 1, 2016 - June 30, 2017</option>
          <option value="17">July 1, 2017 - June 30, 2018</option>
        </select>
      </td>
    </tr>
    <tr></tr>
    <tr></tr>
  </tbody>
</table>

编辑(12.9.2016):仍然坚持这一点。

我能够获取旧窗口和新窗口的窗口句柄,并且可以在使用 driver.title 切换到新窗口后获取新窗口的标题。鉴于一旦打开新窗口我就知道它的标题,我认为将该标题传递给 move_to.window(new_window_title_here) 会起作用。但是,当我调用该函数时,Selenium 会抛出 NoSuchWindowException。当我调用 switch_to.window(new_window_handle_here) 时,我的打印语句确认我正在切换到新窗口,但我仍然无法获取任何元素。我曾尝试通过 xpath、名称和 CSS 选择器以零运气抓取它们。这可能是 Selenium 或 Python 绑定的错误吗?

【问题讨论】:

  • 您是否在使用find_element_by_name 而应该使用find_element_by_id
  • @DavidCullen 没有为我正在寻找的元素提供 ID。我更喜欢使用 xpath 查询,例如 "//select[@name = \"rotationsetID\"]" 但我也尝试使用名称。
  • 我问的原因是您有一个使用find_element_by_idprogramID 查询。所以我想知道scheduleID 是否实际上是id 而不是name
  • @DavidCullen 是的,很遗憾我没有可使用的 ID。元素名称是唯一给出的东西,find_element_by_id 用于上一页上的另一个元素。
  • 您是否使用过 Chrome 开发者控制台来验证您是否可以找到该元素?

标签: python selenium automated-tests


【解决方案1】:

您的driver 实例应该有一个名为window_handleslist。您应该能够保存当前和所需的窗口句柄并使用driver.switch_to_window 在它们之间切换:

main_window = driver.window_handles[0]
new_window = driver.window_handles[1]
driver.switch_to_window(new_window)
# Do something
driver.switch_to_window(main_window)

【讨论】:

  • 嗨,大卫,这对我不起作用。请参阅我对@Lucas 的回复以及我的编辑。
  • 如果您尝试使用switch_to_window 而不是switch_to.window 会发生什么?你有没有在调试器中运行它以便查看driver.window_handles
  • switch_to_windowswitch_to.window 的弃用版本
  • @David 是的,我已经尝试过 switch_to_window 和 switch_to.window 两种变体。我在 VS Code 中运行,并且能够在控制台中看到我的窗口句柄。看起来 Selenium 正在抓取第二个窗口,但无法找到其中包含的任何元素。
  • 此答案中的代码不正确,因为它假定窗口句柄按打开窗口或选项卡的顺序是常见的谬误。根据W3C WebDriver Specificationwindow_handles 中的窗口句柄是明确无序的。在有两个窗口句柄的情况下,如果您使用windows_handles[1],并且恰好返回与最近打开的窗口关联的句柄,那么您很幸运,并且不能保证每次都能正常工作。
【解决方案2】:

如果您只是在点击链接后打开了一个新标签,它应该window_handles 列表中的最后一个标签,所以理论上您可以这样做:

driver.switch_to.window(driver.window_handles[-1])

更好的做法是在打开链接之前跟踪第一个窗口句柄并选择打开链接后出现的新窗口句柄。

【讨论】:

  • 这对我不起作用。我已尝试按照您的建议将 driver.window_handles[0] 和 driver.window_handles[-1] 分别存储为旧的和新的。如果您看到我的编辑,我还提到了作用于新窗口的第一行代码从下拉列表中选择一个项目,这确实有效,但随后我在刚刚操作的元素上立即收到 NoSuchElementException。跨度>
  • 我很困惑,在您的示例中,您没有两次点击下拉菜单,但您说第一次确实有效
  • 听起来您进入了正确的窗口。唯一会发生的事情是您需要等待更长时间,或者您的选择器错误。您确定下拉菜单在新窗口中而不是旧窗口中吗?如果不查看页面,这将很难进一步排除故障
  • 我已经添加了我想要抓取的 HTML。不幸的是,在检查了你刚才建议的所有内容之后,我更加茫然了。
  • 我必须重申,不应依赖window_handles 属性中的窗口句柄排序。有关更多详细信息,请参阅 cmets 关于此问题的其他答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多