WebDriver 文档

入门指南
WebDriver 以本地化方式驱动浏览器,就像用户在本地或使用 Selenium 服务器的远程机器上所做的那样,这标志着浏览器自动化的飞跃。

Selenium WebDriver 指的是语言绑定和各个浏览器控制代码的实现。 这通常被称为 WebDriver。

Selenium WebDriver 是 W3C 推荐标准

  • WebDriver 被设计成一个简单和简洁的编程接口。
  • WebDriver 是一个简洁的面向对象 API。
  • 它能有效地驱动浏览器。

了解组件

使用 WebDriver 构建测试套件需要您理解并有效地使用许多不同的组件。就像软件中的一切一样, 不同的人对同一个想法使用不同的术语。下面是在这个描述中如何使用术语的细分。

专业术语

  • API: 应用程序编程接口。这是一组用来操作 WebDriver 的 “命令”。
  • 库: 一个代码模块,它包含 api 和实现这些 api 所需的代码。库是对应于具体的语言的,例如 Java 的 .jar 文件,.NET
    的 .dll 文件,等等。
  • 驱动程序: 负责控制实际的浏览器。大多数驱动程序是由浏览器厂商自己创建的。
    驱动程序通常是与浏览器一起在系统上运行的可执行模块,而不是在执行测试套件的系统上。 (尽管它们可能是同一个系统。) 注意:
    有些人把驱动称为代理。
  • 框架: 用于支持 WebDriver 套件的附加库。这些框架可能是测试框架,如 JUnit 或 NUnit。
    它们也可能是支持自然语言特性的框架,如 Cucumber 或 Robotium。还可以编写和使用框架来操作或配置被测试的系统、
    数据创建、测试预言等等。

组成部分

至少,WebDriver 通过一个驱动程序与浏览器对话。通信有两种方式: WebDriver 通过驱动程序向浏览器传递命令, 然后通过相同的路径接收信息。

驱动程序是特定于浏览器的,例如 ChromeDriver 对应于谷歌的 Chrome/Chromium, GeckoDriver 对应于 Mozilla 的 Firefox 的,等等。驱动程序在与浏览器相同的系统上运行。 这可能与执行测试本身的系统相同,也可能不同。

上面这个简单的例子就是 _直接_通信。与浏览器的通信也可以是通过 Selenium 服务器或 RemoteWebDriver 进行的 _远程_通信。RemoteWebDriver 与驱动程序和浏览器运行在同一个系统上。

远程通信也可以使用 Selenium Server 或 Selenium Grid 进行,这两者依次与主机系统上的驱动程序进行通信

应用框架

WebDriver 有且只有一个任务: 通过上面的任何方法与浏览器通信。WebDriver 对测试一窍不通:它不知道如何比较事物、 断言通过或失败,当然它也不知道报告或 Given/When/Then 语法。

这就是各种框架发挥作用的地方。至少你需要一个与绑定语言相匹配的测试框架,比如. NET 的 NUnit, Java 的 JUnit, Ruby 的 RSpec 等等。

测试框架负责运行和执行 WebDriver 以及测试中相关步骤。因此,您可以认为它看起来类似于下图。


像 Cucumber 这样的自然语言框架/工具可能作为上图中测试框架框的一部分存在, 或者它们可能将测试框架完全封装在它们自己的实现中。

驱动要求

通过 WebDriver,Selenium 支持市面上所有主流的浏览器,如 Chrom(ium)、Firefox、 Internet Explorer、Opera 和 Safari。 尽管并非所有浏览器都对远程控制提供官方支持, 但 WebDriver 尽可能使用浏览器的内置自动化支持来驱动浏览器。

WebDriver 的目标是尽可能模拟真实用户与浏览器的交互。
在不同的浏览器中,这可能有不同的级别。有关不同驱动程序特性的详细信息, 请参见 驱动程序特性。

尽管所有的驱动程序共享一个面向用户的界面来控制浏览器,但它们设置浏览器会话的方式略有不同。 由于许多驱动程序实现是由第三方提供的,所以它们不包括在标准的 Selenium 发行版中。

驱动程序实例化、配置文件管理和各种特定于浏览器的设置都是具体参数的例子,这些参数根据浏览器有 不同的需求。本节介绍了使用不同浏览器的基本要求。

将可执行文件添加到 PATH 中

大多数驱动程序需要 Selenium 额外的可执行文件才能与浏览器通信。您可以在启动 WebDriver 之前手动指定可执行文件的存放位置,但这会使测试的可移植性降低,因为可执行文件必须位于每台 计算机上的同一位置,或包含在测试代码存储库中。

通过将包含 WebDriver 二进制文件的文件夹添加到系统 path 环境变量中,Selenium 将能够找到其他二进制文件,而无需您的测试代码来定位驱动程序的确切位置。

  • 创建一个目录来放置可执行文件,例如 C:\WebDriver\bin 或 /opt/WebDriver/bin
  • 将目录添加到您的 path 中:
    • 在 Windows 上 - 以管理员身份打开命令提示符,然后运行以下命令将目录永久添加到计算机上所有用户的路径中:
setx /m path "%path%;C:\WebDriver\bin\"
  • 在 macOS 和 Linux 上的 Bash 用户 - 在终端中:
export PATH=$PATH:/opt/WebDriver/bin >> ~/.profile
  • 现在您可以测试更改了。关闭所有打开的命令提示符,然后打开一个新的提示符。 输入您在上一步创建的文件夹中的某一个二进制文件的名称,例如:
chromedriver
  • 如果您的 PATH 配置正确,您将看到一些有关驱动程序启动的输出:
Starting ChromeDriver 2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1) on port 9515
Only local connections are allowed.

您可以通过按 Ctrl + C 重新获得对命令提示符的控制。

快速参考

Chromium/Chrome Windows/macOS/Linux 谷歌 下载
火狐 Windows/macOS/Linux Mozilla 下载

Chromium/Chrome
要驱动 Chrome 或 Chromium,您必须下载 chromedriver 并将其放在系统路径上的文件夹中。

在 Linux 或 macOS 上,这意味着修改 PATH 环境变量。通过执行以下命令,您可以看到由冒号分隔的目录组成的系统路径:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

要在路径上包含 chromedriver(如果还没有的话),请确保包含 chromedriver 二进制文件的父目录。 下面的行将设置当前 PATH 环境变量的内容,在冒号后面添加一个额外的路径:

$ export PATH="$PATH:/path/to/chromedriver"

当您的路径上有 chromedriver 时,您应该可以从任何目录执行 chromedriver 可执行文件。

要实例化 Chrome/Chromium 会话,您可以执行以下操作:

#简单赋值
from selenium.webdriver import Chromedriver = Chrome()#或者使用上下文管理器
from selenium.webdriver import Chromewith Chrome() as driver:#你自己的代码放在这个缩进中

请记住,您必须设置 chromedriver 可执行文件的路径。可以使用下行代码实现:

Chrome(executable_path='/path/to/chromedriver')

chromedriver 被实现为 WebDriver 远程服务器,该服务器通过公开 Chrome 的内部自动化代理接口来指示浏览器该怎么做。

火狐浏览器

从 Selenium 3 开始,Mozilla 通过 geckodriver 接管了火狐驱动程序的实现。火狐的新驱动程序被称为 geckodriver,可与 Firefox 48 及更高版本一起使用。 由于正在开发 Firefox WebDriver,因此 Firefox 版本越新,支持越好。

由于 geckodriver 是默认新的启动火狐浏览器的方式,您可以像 Selenium 2 那样实例化火狐浏览器:

#简单赋值
from selenium.webdriver import Firefoxdriver = Firefox()
#或者使用上下文管理器
from selenium.webdriver import Firefoxwith Firefox() as driver:#你自己的代码放在这个缩进中

如果您不想使用 PATH 设置 geckodriver 的位置,请在代码中设置 geckodriver 的位置:

Firefox(executable_path='/path/to/geckodriver')

也可以在运行时设置属性:

mvn test -Dwebdriver.gecko.driver=/path/to/geckodriver

当前,可以通过安装 Firefox 47.0.1 或 45 ESR 并指定 marionette 功能为 false 来还原到功能更强大的旧版 Firefox 驱动程序。Firefox 的更高版本不再兼容。

模拟浏览器

HtmlUnit
HtmlUnit 是一个 “针对 Java 程序的无图形界面浏览器”。它为 HTML 文档建模,并提供一个 API, 允许您调用页面、填写表单、单击链接等。它支持 JavaScript,能够使用 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 IE。它已经迁移到一个新位置 了。 源文件保存在 svn 上。

PhantomJS
PhantomJS 是一款基于 Webkit 的无头浏览器,尽管它的版本比谷歌 Chrome 或 Safari 要老得多。虽然曾经很流行, 但现在明智的做法是避免 PhantomJS。这个项目 从 8 月 5 日起 就一直没有被维护过,所以尽管网络会继续变化,PhantomJS 也不会更新。在谷歌宣布可以无头运行 Chrome 之后,现在 Mozilla 的火狐浏览器也提供了这个功能。

WebDriver Bidi APIs

在Selenium 4中, 引入了新的事件API, 使用户能够在事件发生时从浏览器捕获事件, 并非WebDriver用于其他API的传统请求/响应方法.

WebDriver将在内部创建针对浏览器的WebSocket连接, 用于传输事件和命令.

随着Selenium项目更多地用于实际案例, 相应的API列表将不断扩充. 如果缺少API, 请提出功能请求.

变化监测
变化监测是一种能力, 用于当特定元素的DOM发生变化时, 得以通过WebDriver BiDi捕获事件.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWaitdriver = webdriver.Chrome()
async with driver.log.mutation_events() as event:pages.load("dynamic.html")driver.find_element(By.ID, "reveal").click()WebDriverWait(driver, 5)\.until(EC.visibility_of(driver.find_element(By.ID, "revealed")))assert event["attribute_name"] == "style"
assert event["current_value"] == ""
assert event["old_value"] == "display:none;"

定位元素

使用 WebDriver 时要学习的最基本的技术之一是如何查找页面上的元素。
findElement(By) 方法返回另一个基本对象类型 WebElement。

WebDriver 代表浏览器
WebElement 表示特定的 DOM 节点(控件,例如链接或输入栏等)

cheese = driver.find_element(By.ID, “cheese”)
cheddar = cheese.find_elements_by_id(“cheddar”)

WebDriver 和 WebElement 类型都实现了 搜索上下文 接口。在 WebDriver 中,这称为 基于角色的接口。基于角色的接口允许你确定特定的驱动程序实现是否支持给定的功能。

cheddar = driver.find_element_by_css_selector("#cheese #cheddar")

定位多个元素

最喜欢的奶酪的订单列表:

复数版本 findElements(By) 。此方法返回 web 元素的集合。如果只找到一个元素,它仍然返回(一个元素的)集合。如果没有元素被定位器匹配到,它将返回一个空列表。

mucho_cheese = driver.find_elements_by_css_selector("#cheese li")

8 种不同的内置元素定位策略

class name 定位class属性与搜索值匹配的元素(不允许使用复合类名)
css selector 定位 CSS 选择器匹配的元素
id 定位 id 属性与搜索值匹配的元素
name 定位 name 属性与搜索值匹配的元素
link text 定位link text可视文本与搜索值完全匹配的锚元素
partial link text 定位link text可视文本部分与搜索值部分匹配的锚点元素。如果匹配多个元素,则只选择第一个元素。
tag name 定位标签名称与搜索值匹配的元素
xpath 定位与 XPath 表达式匹配的元素

Relative Locators

findElement 方法现在支持witTagName()新方法其可返回RelativeLocator相对定位对象。

Selenium是通过使用JavaScript函数 getBoundingClientRect() 来查找相对元素的。这个函数能够返回对应元素的各种属性例如:右,左,下,上。

from selenium.webdriver.support.relative_locator import with_tag_name

above() 元素上 返回当前指定元素位置上方的WebElement对象
passwordField = driver.find_element(By.ID, “password”)
emailAddressField = driver.find_element(with_tag_name(“input”).above(passwordField))

below() 元素下 返回当前指定元素位置下方的WebElement对象
emailAddressField = driver.find_element(By.ID, “email”)
passwordField = driver.find_element(with_tag_name(“input”).below(emailAddressField))

toLeftOf() 元素左 返回当前指定元素位置左方的WebElement对象
submitButton = driver.find_element(By.ID, “submit”)
cancelButton = driver.find_element(with_tag_name(“button”).to_left_of(submitButton))

toRightOf() 元素右 返回当前指定元素位置右方的WebElement对象
cancelButton = driver.find_element(By.ID, “cancel”)
submitButton = driver.find_element(with_tag_name(“button”).to_right_of(cancelButton))

near() 附近 返回当前指定元素位置附近大约px5050像素的WebElement对象
emailAddressLabel = driver.find_element(By.ID, “lbl-email”)
emailAddressField = driver.find_element(with_tag_name(“input”).near(emailAddressLabel))

操控浏览器

浏览器导航

打开网站

driver.get("https://selenium.dev")

driver.current_url
driver.back()
driver.forward()
driver.refresh()
driver.title

窗口和标签页

WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。

driver.current_window_handle

切换窗口或标签页

单击在 <a href=“https://seleniumhq.github.io"target=”_blank”>新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 启动驱动程序
with webdriver.Firefox() as driver:# 打开网址driver.get("https://seleniumhq.github.io")# 设置等待wait = WebDriverWait(driver, 10)# 存储原始窗口的 IDoriginal_window = driver.current_window_handle# 检查一下,我们还没有打开其他的窗口assert len(driver.window_handles) == 1# 单击在新窗口中打开的链接driver.find_element(By.LINK_TEXT, "new window").click()# 等待新窗口或标签页wait.until(EC.number_of_windows_to_be(2))# 循环执行,直到找到一个新的窗口句柄for window_handle in driver.window_handles:if window_handle != original_window:driver.switch_to.window(window_handle)break# 等待新标签页完成加载内容wait.until(EC.title_is("SeleniumHQ Browser Automation"))
## 创建新窗口(或)新标签页并且切换

Selenium 4 提供了一个新的 api NewWindow, 它创建一个新选项卡 (或) 新窗口并自动切换到它。
创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。

注意: 该特性适用于 Selenium 4 及其后续版本。

Java Python C# Ruby JavaScript Kotlin

打开新标签页并切换到新标签页

driver.switch_to.new_window(‘tab’)

打开一个新窗口并切换到新窗口

driver.switch_to.new_window(‘window’)
关闭窗口或标签页
当你完成了一个窗口或标签页的工作时,_并且_它不是浏览器中最后一个打开的窗口或标签页时,你应该关闭它并切换回你之前使用的窗口。 假设您遵循了前一节中的代码示例,您将把前一个窗口句柄存储在一个变量中。把这些放在一起,你会得到:

Java Python C# Ruby JavaScript Kotlin

#关闭标签页或窗口
driver.close()

#切回到之前的标签页或窗口
driver.switch_to.window(original_window)
如果在关闭一个窗口后忘记切换回另一个窗口句柄,WebDriver 将在当前关闭的页面上执行,并触发一个 No Such Window Exception 无此窗口异常。必须切换回有效的窗口句柄才能继续执行。

在会话结束时退出浏览器
当你完成了浏览器会话,你应该调用 quit 退出,而不是 close 关闭:

Java Python C# Ruby JavaScript Kotlin
driver.quit()
退出将会
关闭所有与 WebDriver 会话相关的窗口和选项卡
结束浏览器进程
结束后台驱动进程
通知 Selenium Grid 浏览器不再使用,以便可以由另一个会话使用它(如果您正在使用 Selenium Grid)
调用 quit() 失败将留下额外的后台进程和端口运行在机器上,这可能在以后导致一些问题。

有的测试框架提供了一些方法和注释,您可以在测试结束时放入 teardown() 方法中。

Java Python C# Ruby JavaScript Kotlin

unittest teardown

https://docs.python.org/3/library/unittest.html?highlight=teardown#unittest.TestCase.tearDown

def tearDown(self):
self.driver.quit()
如果不在测试上下文中运行 WebDriver,您可以考虑使用 try / finally,这是大多数语言都提供的, 这样一个异常处理仍然可以清理 WebDriver 会话。

Java Python C# Ruby JavaScript Kotlin

try:
#WebDriver 代码…
finally:
driver.quit()
Python 的 WebDriver 现在支持 Python 上下文管理器,当使用 with 关键字时,可以在执行结束时自动退出驱动程序。

with webdriver.Firefox() as driver:

WebDriver 代码…

在此缩进位置后 WebDriver 会自动退出

Frames and Iframes
框架是一种现在已被弃用的方法,用于从同一域中的多个文档构建站点布局。除非你使用的是 HTML5 之前的 webapp,否则你不太可能与他们合作。内嵌框架允许插入来自完全不同领域的文档,并且仍然经常使用。

如果您需要使用框架或 iframe, WebDriver 允许您以相同的方式使用它们。考虑 iframe 中的一个按钮。 如果我们使用浏览器开发工具检查元素,我们可能会看到以下内容:

Java Python C# Ruby JavaScript Kotlin

这不会工作

driver.find_element(By.TAG_NAME, ‘button’).click()
但是,如果 iframe 之外没有按钮,那么您可能会得到一个 no such element 无此元素 的错误。 这是因为 Selenium 只知道顶层文档中的元素。为了与按钮进行交互,我们需要首先切换到框架, 这与切换窗口的方式类似。WebDriver 提供了三种切换到帧的方法。

使用 WebElement
使用 WebElement 进行切换是最灵活的选择。您可以使用首选的选择器找到框架并切换到它。

Java Python C# Ruby JavaScript Kotlin

存储网页元素

iframe = driver.find_element(By.CSS_SELECTOR, “#modal > iframe”)

切换到选择的 iframe

driver.switch_to.frame(iframe)

单击按钮

driver.find_element(By.TAG_NAME, ‘button’).click()
使用 name 或 id
如果您的 frame 或 iframe 具有 id 或 name 属性,则可以使用该属性。如果名称或 id 在页面上不是唯一的, 那么将切换到找到的第一个。

Java Python C# Ruby JavaScript Kotlin

通过 id 切换框架

driver.switch_to.frame(‘buttonframe’)

单击按钮

driver.find_element(By.TAG_NAME, ‘button’).click()
使用索引
还可以使用frame的索引, 例如可以使用JavaScript中的 window.frames 进行查询.

Java Python C# Ruby JavaScript Kotlin

切换到第 2 个框架

driver.switch_to.frame(1)
离开框架
离开 iframe 或 frameset,切换回默认内容,如下所示:

Java Python C# Ruby JavaScript Kotlin

切回到默认内容

driver.switch_to.default_content()
窗口管理
屏幕分辨率会影响 web 应用程序的呈现方式,因此 WebDriver 提供了移动和调整浏览器窗口大小的机制。

获取窗口大小
获取浏览器窗口的大小(以像素为单位)。

Java Python C# Ruby JavaScript Kotlin

分别获取每个尺寸

width = driver.get_window_size().get(“width”)
height = driver.get_window_size().get(“height”)

或者存储尺寸并在以后查询它们

size = driver.get_window_size()
width1 = size.get(“width”)
height1 = size.get(“height”)
设置窗口大小
恢复窗口并设置窗口大小。

Java Python C# Ruby JavaScript Kotlin
driver.set_window_size(1024, 768)
得到窗口的位置
获取浏览器窗口左上角的坐标。

Java Python C# Ruby JavaScript Kotlin

分别获取每个尺寸

x = driver.get_window_position().get(‘x’)
y = driver.get_window_position().get(‘y’)

或者存储尺寸并在以后查询它们

position = driver.get_window_position()
x1 = position.get(‘x’)
y1 = position.get(‘y’)
设置窗口位置
将窗口移动到设定的位置。

Java Python C# Ruby JavaScript Kotlin

将窗口移动到主显示器的左上角

driver.set_window_position(0, 0)
最大化窗口
扩大窗口。对于大多数操作系统,窗口将填满屏幕,而不会阻挡操作系统自己的菜单和工具栏。

Java Python C# Ruby JavaScript Kotlin
driver.maximize_window()
最小化窗口
最小化当前浏览上下文的窗口. 这种命令的精准行为将作用于各个特定的窗口管理器.

最小化窗口通常将窗口隐藏在系统托盘中.

注意: 此功能适用于Selenium 4以及更高版本.

Java Python C# Ruby JavaScript Kotlin
driver.minimize_window()
全屏窗口
填充整个屏幕,类似于在大多数浏览器中按下 F11。

Java Python C# Ruby JavaScript Kotlin
driver.fullscreen_window()
屏幕截图
用于捕获当前浏览上下文的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.

Java Python C# Ruby JavaScript Kotlin

from selenium import webdriver

driver = webdriver.Chrome()

Navigate to url

driver.get(“http://www.example.com”)

Returns and base64 encoded string into image

driver.save_screenshot(’./image.png’)

driver.quit()
元素屏幕截图
用于捕获当前浏览上下文的元素的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.

Java Python C# Ruby JavaScript Kotlin

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

Navigate to url

driver.get(“http://www.example.com”)

ele = driver.find_element(By.CSS_SELECTOR, ‘h1’)

Returns and base64 encoded string into image

ele.screenshot(’./image.png’)

driver.quit()
执行脚本
在当前frame或者窗口的上下文中,执行JavaScript代码片段.

Java Python C# Ruby JavaScript Kotlin

// Stores the header element
let header = await driver.findElement(By.css(‘h1’));

// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript(‘return arguments[0].innerText’, header);
打印页面
打印当前浏览器内的页面

注意: 此功能需要无头模式下的Chromium浏览器

Java Python C# Ruby JavaScript Kotlin

from selenium.webdriver.common.print_page_options import PrintOptions

print_options = PrintOptions()
print_options.page_ranges = ['1-2']driver.get("printPage.html")base64code = driver.print_page(print_options)

等待

WebDriver通常可以说有一个阻塞API。因为它是一个指示浏览器做什么的进程外库,而且web平台本质上是异步的,所以WebDriver不跟踪DOM的实时活动状态。这伴随着一些我们将在这里讨论的挑战。

根据经验,大多数由于使用Selenium和WebDriver而产生的间歇性问题都与浏览器和用户指令之间的 竞争条件 有关。例如,用户指示浏览器导航到一个页面,然后在试图查找元素时得到一个 no such element 的错误。

考虑下面的文档:

<!doctype html>
<meta charset=utf-8>
<title>Race Condition Example</title><script>var initialised = false;window.addEventListener("load", function() {var newElement = document.createElement("p");newElement.textContent = "Hello from JavaScript!";document.body.appendChild(newElement);initialised = true;});</script>

这个 WebDriver的说明可能看起来很简单:

driver.navigate("file:///race_condition.html")
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"

这里的问题是WebDriver中使用的默认页面加载策略页面加载策略听从document.readyState在返回调用 navigate 之前将状态改为"complete" 。因为p元素是在文档完成加载之后添加的,所以这个WebDriver脚本可能是间歇性的。它“可能”间歇性是因为无法做出保证说异步触发这些元素或事件不需要显式等待或阻塞这些事件。

幸运的是,WebElement接口上可用的正常指令集——例如 WebElement.click 和 WebElement.sendKeys—是保证同步的,因为直到命令在浏览器中被完成之前函数调用是不会返回的(或者回调是不会在回调形式的语言中触发的)。高级用户交互APIs,键盘和鼠标是例外的,因为它们被明确地设计为“按我说的做”的异步命令。

等待是在继续下一步之前会执行一个自动化任务来消耗一定的时间。

为了克服浏览器和WebDriver脚本之间的竞争问题,大多数Selenium客户都附带了一个 wait 包。在使用等待时,您使用的是通常所说的显式等待。

显式等待

显示等待 是Selenium客户可以使用的命令式过程语言。它们允许您的代码暂停程序执行,或冻结线程,直到满足通过的 条件 。这个条件会以一定的频率一直被调用,直到等待超时。这意味着只要条件返回一个假值,它就会一直尝试和等待

由于显式等待允许您等待条件的发生,所以它们非常适合在浏览器及其DOM和WebDriver脚本之间同步状态。

为了弥补我们之前的错误指令集,我们可以使用等待来让 findElement 调用等待直到脚本中动态添加的元素被添加到DOM中:

from selenium.webdriver.support.ui import WebDriverWait
def document_initialised(driver):return driver.execute_script("return initialised")driver.navigate("file:///race_condition.html")
WebDriverWait(driver).until(document_initialised)
el = driver.find_element(By.TAG_NAME, "p")
assert el.text == "Hello from JavaScript!"

我们将 条件 作为函数引用传递, 等待 将会重复运行直到其返回值为true。“truthful”返回值是在当前语言中计算为boolean true的任何值,例如字符串、数字、boolean、对象(包括 WebElement )或填充(非空)的序列或列表。这意味着 空列表 的计算结果为false。当条件为true且阻塞等待终止时,条件的返回值将成为等待的返回值。

有了这些知识,并且因为等待实用程序默认情况下会忽略 no such element 的错误,所以我们可以重构我们的指令使其更简洁:

from selenium.webdriver.support.ui import WebDriverWaitdriver.navigate("file:///race_condition.html")
el = WebDriverWait(driver).until(lambda d: d.find_element_by_tag_name("p"))
assert el.text == "Hello from JavaScript!"

在这个示例中,我们传递了一个匿名函数(但是我们也可以像前面那样显式地定义它,以便重用它)。传递给我们条件的第一个,也是唯一的一个参数始终是对驱动程序对象 WebDriver 的引用。在多线程环境中,您应该小心操作传入条件的驱动程序引用,而不是外部范围中对驱动程序的引用。

因为等待将会吞没在没有找到元素时引发的 no such element 的错误,这个条件会一直重试直到找到元素为止。然后它将获取一个 WebElement 的返回值,并将其传递回我们的脚本。

如果条件失败,例如从未得到条件为真实的返回值,等待将会抛出/引发一个叫 timeout error 的错误/异常。

选项

等待条件可以根据您的需要进行定制。有时候是没有必要等待缺省超时的全部范围,因为没有达到成功条件的代价可能很高。

等待允许你传入一个参数来覆盖超时:

WebDriverWait(driver, timeout=3).until(some_condition)

预期的条件

由于必须同步DOM和指令是相当常见的情况,所以大多数客户端还附带一组预定义的 预期条件 。顾名思义,它们是为频繁等待操作预定义的条件。

不同的语言绑定提供的条件各不相同,但这只是其中一些:

  • alert is present
  • element exists
  • element is visible
  • title contains
  • title is
  • element staleness
  • visible text

您可以参考每个客户端绑定的API文档,以找到期望条件的详尽列表:

  • Java’s org.openqa.selenium.support.ui.ExpectedConditions class
  • Python’s selenium.webdriver.support.expected_conditions class
  • .NET’s OpenQA.Selenium.Support.UI.ExpectedConditions type

隐式等待

还有第二种区别于显示等待 类型的 隐式等待 。通过隐式等待,WebDriver在试图查找_任何_元素时在一定时间内轮询DOM。当网页上的某些元素不是立即可用并且需要一些时间来加载时是很有用的。

默认情况下隐式等待元素出现是禁用的,它需要在单个会话的基础上手动启用。将显式等待和隐式等待混合在一起会导致意想不到的结果,就是说即使元素可用或条件为真也要等待睡眠的最长时间。

警告: 不要混合使用隐式和显式等待。这样做会导致不可预测的等待时间。例如,将隐式等待设置为10秒,将显式等待设置为15秒,可能会导致在20秒后发生超时。

隐式等待是告诉WebDriver如果在查找一个或多个不是立即可用的元素时轮询DOM一段时间。默认设置为0,表示禁用。一旦设置好,隐式等待就被设置为会话的生命周期。

driver = Firefox()
driver.implicitly_wait(10)
driver.get("http://somedomain/url_that_delays_loading")
my_dynamic_element = driver.find_element(By.ID, "myDynamicElement")

流畅等待

流畅等待实例定义了等待条件的最大时间量,以及检查条件的频率。

用户可以配置等待来忽略等待时出现的特定类型的异常,例如在页面上搜索元素时出现的NoSuchElementException。

driver = Firefox()
driver.get("http://somedomain/url_that_delays_loading")
wait = WebDriverWait(driver, 10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))

Selenium 008 WebDriver 文档相关推荐

  1. Selenium用户指南 - 第一章 Selenium 2.0 文档修订注解

    From: http://blog.csdn.net/planisnothing/article/details/7234995 Selenium 2.0 文档修订注解 你好,欢迎!文档团队欢迎你,并 ...

  2. 【坑】金山文档批量下载技巧记录(Python+JS)

    文章目录 序言 requests请求出现的问题 selenium代码分析 JS下载代码解析 总结 序言 截至本文发布,在金山文档网页版中,如果需要同时下载2个及以上的文件,则必须开通会员.很容易想到可 ...

  3. 爬虫文档学习 xpath bs4 selenium scrapy...

    爬虫 一.介绍 1.什么是爬虫 1.1 爬虫(Spider)的概念 爬虫用于爬取数据, 又称之为数据采集程序. 爬取的数据来源于网络,网络中的数据可以是由Web服务器(Nginx/Apache).数据 ...

  4. selenium python文档_selenium+python实现百度文库word文档抓取

    更新这个代码最近又改了一点,另外和其他一些小程序一起放在了一个jupyter notebook里,现在挂在github上面.github现在对jupyter notebook的支持非常的好,甚至可以直 ...

  5. python selenium中文文档-selenium-python中文版文档

    安装 1.1. 简介 Selenium Python提供了一个简单的绑定式API来使用Selenium WebDriver编写功能/验收测试.通过Selenium Python API,您可以以一种直 ...

  6. selenium + 石墨文档 自动实现在固定位置写入文字

    作为宿舍长,这学期又增加了一个在石墨文档上晚上签到的任务,于是便想敲个代码自动实现这一过程. 首先,我得承认,这篇文章中的代码有点笨,适应性有点差,大家就把他作为一些函数和坑的文章吧. 前期准备 环境 ...

  7. selenium实现高校班级打卡-石墨文档每日一报自动化

    selenium实现高校班级打卡-石墨文档每日一报自动化 selenium-WEB自动化工具 selenium-WEB自动化工具 Selenium是一个用于Web应用程序测试的工具.Selenium测 ...

  8. python爬虫实战:selenium下载百度文库文档

    利用selenium进行页面操作 草草地写了一下,文字是爬下来了,但是还有格式等问题,遇到复杂的文档可能不通用,有点蛋疼. 用安卓模拟登陆,让页面简单一点,电脑网页有点复杂. 之后有空再来改进 fro ...

  9. python selenium爬虫保存_爬虫之自动保存文档-使用python/selenium

    网络抓取的时候会碰到需要从网站下载文件的情况.下面提供两种方法: 1.  selenium + firefox + firefoxProfile 核心要点是在firefox中设置相关的下载参数,然后在 ...

最新文章

  1. Java:RMI远程调用
  2. Huggingface简介及BERT tansformer 开源
  3. 8 cocos2dx添加场景切换效果,控制场景切换彻底完成之后再执行动画
  4. 跟着微信后台团队学习分布式一致性协议
  5. wireshark基本使用及介绍
  6. PL/SQL-FOR UPDATE 与 FOR UPDATE OF的区别
  7. SuperSocketClientEngine
  8. 激光雷达在自动驾驶中的应用
  9. 通过 电脑快捷键 高效利用时间
  10. 卷积神经网络学习路线(十一)| Stochastic Depth(随机深度网络)
  11. 【历史上的今天】7 月 23 日:Novell 挑战微软;计算机界的教育家出生;第一颗 Landsat 卫星发射
  12. 计算机导论第七章数据库基础,计算机导论教学大纲
  13. Unity3D 模型分块
  14. win7网络里面没有计算机,Win7没有无线网络选项教你完美解决
  15. python爬取网易云音乐飙升榜音乐_Python爬虫实战,30行代码轻松爬取网易云音乐热歌榜...
  16. 2、软件造价总结(主要基准数据)
  17. 02 FinalReference.referent的回收时机
  18. Github大文件下载不怕啦
  19. Linux内核入门-- likely和unlikely
  20. 20200607:根据中证800指数最近十年历史P/b分位数确认基金目标仓位

热门文章

  1. android 实现性别头像,Android 实现切圆图作为头像使用实例
  2. c语言ch2什么意思,ch2-3C语言的语法.ppt
  3. 百度移动应用安卓_【IOS+安卓应用】最新百度网盘,下载不限速,来了来了......
  4. 河北工业大学计算机学院导师,河北工业大学
  5. 每周福利--自费送10套机械键盘,值得你拥有!
  6. PowerDesigner,如何将Mysql数据库建表语句转化成Oracle数据库建表语句。
  7. SEO优化报价_网站优化报价_SEO网站报价——捷弘SEO
  8. 讯为开发板移植linux,迅为I.MX6ULL开发板移植Linux5.4内核教程
  9. 微信小程序(游戏)----五子棋(棋盘,重置,对弈)
  10. python水印检测_TensorFlow Lite+OpenCV实现移动端水印的检测与去除