08 - 数据收集 - 网页采集工具Selenium

Selenium

官网地址:https://www.selenium.dev/

文档地址:https://www.selenium.dev/documentation/

源码地址:https://github.com/seleniumhq/selenium

Selenium 是一个包含一系列工具和库的统称,这些工具和库支持 web 浏览器的自动化。

它提供了用于模拟用户与浏览器交互的扩展、用于扩展浏览器分配的分发服务器,以及用于实现 W3C WebDriver 规范的基础设施,该规范允许您为所有主要 web 浏览器编写可互换的代码。

Selenium 的核心是 WebDriver,它是一个编写指令集的接口,可以在许多浏览器中交替运行。安装完所有内容后,只需编写几行代码即可进入浏览器。您可以在编写第一个 Selenium 脚本中找到一个更全面的示例。

复制代码
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://selenium.dev")
driver.quit()

Selenium 不仅仅是一个工具或 API;它包括许多工具。

名称 说明
WebDriver 如果您开始使用桌面网站或移动网站测试自动化,那么您将使用 WebDriver apiWebDriver 使用浏览器厂商提供的浏览器自动化 api 来控制浏览器并运行测试。这就好像是一个真正的用户在操作浏览器一样。由于 WebDriver 不需要用应用程序代码编译它的 API,所以它不是侵入式的。因此,您正在测试您推出的同一个应用程序
IDE 集成开发环境(Integrated Development EnvironmentIDE)是用于开发 Selenium 测试用例的工具。它是一个易于使用的 ChromeFirefox 扩展,通常是开发测试用例的最有效方法。它使用现有的 Selenium 命令在浏览器中为您记录用户的操作,并使用该元素的上下文定义的参数。这不仅节省了时间,而且是学习 Selenium 脚本语法的一种极好的方式
Grid Selenium Grid 允许您在不同平台上的不同机器上运行测试用例。触发测试用例的控制在本端,当测试用例被触发后,由远端自动执行。 在开发 WebDriver 测试之后,您可能需要在多个浏览器和操作系统组合上运行测试。这就是 Grid 出现的地方。

因为要进行爬虫开发工作,所以我们重点关注 WebDriver

WebDriver 通过本地浏览器或者使用 Selenium 服务的远程机器模拟用户自动操控浏览器。它标志着浏览器自动化方面的一个飞跃。

Selenium WebDriver W3C推荐标准:

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

安装

首先,您需要为自动化项目安装 Selenium绑定。库的安装过程取决于您选择使用的开发语言。通过检查 Selenium下载页面,以确保使用的是最新版本。每个 Selenium 版本支持的最小Python版本可以在 PyPi 上的 "Supported Python Versions" 中找到。

复制代码
# Python
uv add selenium

第一个应用

首先导入并实例化:

复制代码
from selenium import webdriver
driver = webdriver.Chrome()

然后开始访问页面:

复制代码
driver.get("https://www.selenium.dev/selenium/web/web-form.html")

通过以上代码,我们和该站点建立一个 Session 连接并获取请求页面的信息:

复制代码
title = driver.title

将代码与浏览器的当前状态同步是使用 Selenium 的最大挑战之一。

如果你想定位要操作的元素和想和这个元素互操作的前提是你要确定该元素已经加载到页面上。

隐式等待不是一个好的解决方案,但它是这里最容易演示的,因此我们将使用它作为占位符。展示如何构建一个等待策略:

复制代码
driver.implicitly_wait(0.5)

假设元素已经加载完成,现在我们来演示如果查找元素:

复制代码
text_box = driver.find_element(by=By.NAME, value="my-text")
submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button")

找到了元素,然后通过代码来修改元素的点击事件:

复制代码
text_box.send_keys("Selenium")
submit_button.click()

我们再举个提取文本的例子:

复制代码
message = driver.find_element(by=By.ID, value="message")
text = message.text

最后,结束这次的工作:

复制代码
driver.quit()

会话

创建新会话符合 W3C创建会话的命令。会话是通过初始化一个新的 Driver类对象自动创建的。

每种计算机语言都允许使用以下类(或同等类)的参数创建会话:

  • 通过 options 配置会话的参数选项;默认用于本地,但也可用于远程。
  • 某种形式的 HTTP 客户端配置(不同语言的实现不同)
  • 侦听器
启动会话
复制代码
# 使用Chrome浏览器,不同浏览器不同
driver = webdriver.Chrome(options=options) 
关闭会话
复制代码
driver.quit()

浏览器支持

WebDriver 支持目前主流的浏览器,包括 ChromeEdgeFireFoxInternet ExploreSafari 等。因为各浏览器的特性,除了通用的支持外,针对不同的浏览器,还有特定的支持。

Chrome 浏览器

默认情况下,Selenium 4Chrome v75 及更高版本兼容。注意 Chrome 浏览器版本和 chromedriver 版本必须与主版本保持一致。

ChromeChromium 独有的功能记录在 https://chromedriver.chromium.org/capabilities 页面上。

开始一个 Chrome 会话与基本定义的选项看起来像这样:

复制代码
options = get_default_chrome_options()
driver = webdriver.Chrome(options=options)
参数

从上面代码中可以看到传入了配置参数,args 参数用于在启动浏览器时使用的命令行开关列表。有两个很好的资源可以用来研究这些论点:

  • 用于工具的Chrome标志 :https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
  • Chromium命令行开关列表:https://peter.sh/experiments/chromium-command-line-switches/

常用参数包括 --start-maximized--headless=new--user-data-dir=... 等。给 options 添加一个参数:

复制代码
options.add_argument("--start-maximized")
指定浏览器位置

bin 参数可人工设定要使用的浏览器的本地执行路径。有了这个参数,你可以使用 chromedriver 来驱动各种基于 Chromium 的浏览器。

向选项中添加浏览器位置:

复制代码
options.binary_location = chrome_bin
添加扩展

extensions 参数接受 crx 文件,通过该参数指定 crx 文件;对于未打包的目录,使用 load-extension 参数,正如本文中提到的。

添加一个扩展选项:

复制代码
options.add_extension(extension_file_path)
保持浏览器连接

设置 detach 参数为 true ,只要不向驱动程序发送退出命令,在进程结束后保持浏览器打开。

复制代码
options.add_experimental_option("detach", True)
剔除默认参数

Chromedriver 有几个默认参数用来启动浏览器。如果你不想添加这些参数,把它们传递给 excludeswitch。一个常见的例子是重新打开弹出窗口拦截器。在选项上设置排除的参数:

复制代码
options.add_experimental_option('excludeSwitches', ['disable-popup-blocking'])
日志输出到文件

更改日志输出以保存到指定文件:

复制代码
service = webdriver.ChromeService(log_output=log_path)
日志输出到控制台

将日志输出更改为在控制台中显示:

复制代码
service = webdriver.ChromeService(log_output=subprocess.STDOUT)
设定日志输出级别

有六个可用的日志级别:ALLDEBUGINFOWARNINGSEVERE OFF。注意,--verbose 相当于 --log-level=ALL--silent 相当于 --log-level=OFF,所以这个例子只是一般地设置日志级别:

复制代码
service = webdriver.ChromeService(service_args=['--log-level=DEBUG'], log_output=subprocess.STDOUT)

只有在记录到文件时才有两个功能:

  • 添加日志
  • 可读的时间戳

要使用它们,还需要显式指定日志路径和日志级别。日志输出将由驱动程序管理,而不是进程,因此可能会看到细微的差异。

复制代码
service = webdriver.ChromeService(service_args=['--append-log', '--readable-timestamp'], log_output=log_path)
禁用构建检查

ChromedriverChrome 浏览器版本应该匹配,如果不匹配,驱动程序将出错。如果您禁用构建检查,您可以强制驱动程序与任何版本的 Chrome 一起使用。请注意,这是一个不受支持的特性,不会调查错误。

复制代码
service = webdriver.ChromeService(service_args=['--disable-build-check'], log_output=subprocess.STDOUT)
特定特征 - Casting

你可以驱动 Chrome Cast 设备,包括共享标签:

复制代码
sinks = driver.get_sinks()
        if sinks:
            sink_name = sinks[0]['name']
            driver.start_tab_mirroring(sink_name)
            driver.stop_casting(sink_name)
特定特征 - 网络条件

您可以模拟各种网络条件。

复制代码
 network_conditions = {
        "offline": False,
        "latency": 20,  # 20 ms of latency
        "download_throughput": 2000 * 1024 / 8,  # 2000 kbps
        "upload_throughput": 2000 * 1024 / 8,    # 2000 kbps
    }
    driver.set_network_conditions(**network_conditions)
特定特征 - Logs
复制代码
logs = driver.get_log("browser")
特定特征 - 权限
复制代码
driver.set_permissions('camera', 'denied')
Edge 浏览器

这些是 Microsoft Edge 浏览器特有的功能和特性。
Microsoft Edge 是用 Chromium 实现的,支持的最早版本是 v79 。与 Chrome 类似,edgedriver 的主版本号必须与 Edge 浏览器的主版本号匹配。

复制代码
options = get_default_edge_options()
driver = webdriver.Edge(options=options)
参数

从上面代码中可以看到传入了配置参数,args 参数用于在启动浏览器时使用的命令行开关列表。有两个很好的资源可以用来研究这些论点:

  • 用于工具的Chrome标志 :https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
  • Chromium命令行开关列表:https://peter.sh/experiments/chromium-command-line-switches/

常用参数包括 --start-maximized--headless=new--user-data-dir=... 等。给 options 添加一个参数:

复制代码
options.add_argument("--start-maximized")
指定浏览器位置

bin 参数可人工设定要使用的浏览器的本地执行路径。有了这个参数,你可以使用 chromedriver 来驱动各种基于 Chromium 的浏览器。

向选项中添加浏览器位置:

复制代码
options.binary_location = edge_bin
添加扩展

extensions 参数接受 crx 文件,通过该参数指定 crx 文件;对于未打包的目录,使用 load-extension 参数,正如本文中提到的。

添加一个扩展选项:

复制代码
options.add_extension(extension_file_path)
保持浏览器连接

设置 detach 参数为 true ,只要不向驱动程序发送退出命令,在进程结束后保持浏览器打开。

复制代码
options.add_experimental_option("detach", True)
剔除默认参数

Chromedriver 有几个默认参数用来启动浏览器。如果你不想添加这些参数,把它们传递给 excludeswitch。一个常见的例子是重新打开弹出窗口拦截器。在选项上设置排除的参数:

复制代码
options.add_experimental_option('excludeSwitches', ['disable-popup-blocking'])
日志输出到文件

更改日志输出以保存到指定文件:

复制代码
service = webdriver.EdgeService(log_output=log_path)
日志输出到控制台

将日志输出更改为在控制台中显示:

复制代码
service = webdriver.EdgeService(log_output=subprocess.STDOUT)

该功能要求 seleium v4.11 版本及以上。

设定日志输出级别

有六个可用的日志级别:ALLDEBUGINFOWARNINGSEVERE OFF。注意,--verbose 相当于 --log-level=ALL--silent 相当于 --log-level=OFF,所以这个例子只是一般地设置日志级别:

复制代码
service = webdriver.ChromeService(service_args=['--log-level=DEBUG'], log_output=subprocess.STDOUT)

只有在记录到文件时才有两个功能:

  • 添加日志
  • 可读的时间戳

要使用它们,还需要显式指定日志路径和日志级别。日志输出将由驱动程序管理,而不是进程,因此可能会看到细微的差异。

复制代码
service = webdriver.EdgeService(service_args=['--append-log', '--readable-timestamp'], log_output=log_path)
禁用构建检查

ChromedriverChrome 浏览器版本应该匹配,如果不匹配,驱动程序将出错。如果您禁用构建检查,您可以强制驱动程序与任何版本的 Chrome 一起使用。请注意,这是一个不受支持的特性,不会调查错误。

复制代码
service = webdriver.EdgeService(service_args=['--disable-build-check'], log_output=subprocess.STDOUT)
特定特征 - `Casting``

你可以驱动 Chrome Cast 设备,包括共享标签:

复制代码
sinks = driver.get_sinks()
        if sinks:
            sink_name = sinks[0]['name']
            driver.start_tab_mirroring(sink_name)
            driver.stop_casting(sink_name)
特定特征 - 网络条件

您可以模拟各种网络条件。

复制代码
 network_conditions = {
        "offline": False,
        "latency": 20,  # 20 ms of latency
        "download_throughput": 2000 * 1024 / 8,  # 2000 kbps
        "upload_throughput": 2000 * 1024 / 8,    # 2000 kbps
    }
    driver.set_network_conditions(**network_conditions)
特定特征 - Logs
复制代码
logs = driver.get_log("browser")
特定特征 - 权限
复制代码
 driver.set_permissions('camera', 'denied')

FireFox 浏览器

这些是 Mozilla Firefox 浏览器特有的功能和特性。
Selenium 4 需要 Firefox 78 或更高版本。建议始终使用最新版本的 geckodriver

Firefox 独有的功能可以在 Mozillahttps://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions 页面上找到。

现在开始启动一个Firefox会话,如下所示:

复制代码
options = webdriver.FirefoxOptions()
driver = webdriver.Firefox(options=options)
参数

args 参数用于在启动浏览器时使用的命令行开关列表。常用参数包括 -headless-profile/path/to/profile

options 添加一个参数:

复制代码
options.add_argument("-headless")
指定浏览器执行程序位置

bin 参数可人工设定要使用的浏览器的本地执行路径。有了这个参数,你可以使用 chromedriver 来驱动各种基于 Chromium 的浏览器。

向选项中添加浏览器位置:

复制代码
options.binary_location = edge_bin
Fprofiles

有几种方法可以使用Firefox配置文件。

复制代码
from selenium.webdriver.firefox.options import Options
    from selenium.webdriver.firefox.firefox_profile import FirefoxProfile

    options = Options()
    firefox_profile = FirefoxProfile()
    firefox_profile.set_preference("javascript.enabled", False)
    options.profile = firefox_profile

    driver = webdriver.Firefox(options=options)

注意:无论您是创建一个空的 FirefoxProfile 还是将其指向您自己的 Profile 文件的目录,Selenium 都将创建一个临时目录来存储新 Profile 文件的数据或现有 Profile 文件的副本。每次运行程序时,都会创建一个不同的临时目录。这些目录不会被 Selenium 显式地清除,它们最终会被操作系统删除。但是,如果你想手动删除副本(例如,如果你的配置文件很大),那么该副本的路径将由FirefoxProfile 对象公开。

如果希望使用现有的 Firefox 配置文件,可以传入该配置文件的路径。

日志输出到文件

更改日志输出以保存到指定文件:

复制代码
service = webdriver.FirefoxService(log_output=log_path, service_args=['--log', 'debug'])

该功能有效,需要 Selenium v4.11 版本及以上。

日志输出到控制台

将日志输出更改为在控制台中显示:

复制代码
service = webdriver.FirefoxService(log_output=subprocess.STDOUT)

该功能要求 seleium v4.11 版本及以上。

设定日志输出级别

有六个可用的日志级别:ALLDEBUGINFOWARNINGSEVERE OFF。注意,--verbose 相当于 --log-level=ALL--silent 相当于 --log-level=OFF,所以这个例子只是一般地设置日志级别:

复制代码
service = webdriver.FirefoxService(log_output=log_path, service_args=['--log', 'debug'])
截断日志

Webdriver 日志发送的所有内容,包括大型二进制文件的字符串表示,Firefox在默认情况下会截断行。关闭截断:

复制代码
service = webdriver.FirefoxService(service_args=['--log-no-truncate', '--log', 'debug'], log_output=log_path)
更改 Profile 配置根目录

Profile 文件的默认目录是系统临时目录。如果你没有访问该目录的权限,或者想要在某个特定的地方创建配置文件,你可以更改配置文件的根目录:

复制代码
service = webdriver.FirefoxService(service_args=['--profile-root', temp_dir])
特定特征 - 安装附加组件

Chrome 不同,Firefox 扩展不是作为本问题中提到的功能的一部分添加的,它们是在启动驱动程序后创建的。

以下示例适用于本地 web 驱动程序。对于远程 web 驱动程序,请参考远程 web 驱动程序页面

复制代码
driver.install_addon(addon_path_xpi)
卸载附加组件

卸载插件需要知道它的id。该id可以在安装附加组件时从返回值中获得。

复制代码
driver.uninstall_addon(id)
未签名安装附加组件

当使用未完成或未发布的扩展时,它可能不会被签名。因此,它只能作为"临时"安装。这可以通过传入一个zip文件或一个目录来完成,这里有一个目录的例子:

复制代码
driver.install_addon(addon_path_dir, temporary=True)
整页截图

以下示例适用于本地 web 驱动程序。对于远程 web 驱动程序,请参考远程 web 驱动程序页面。

复制代码
driver.save_full_page_screenshot("full_page_screenshot.png")
上下文

以下示例适用于本地 web 驱动程序。对于远程 web 驱动程序,请参考远程 web 驱动程序页面。

复制代码
with driver.context(driver.CONTEXT_CHROME):
driver.execute_script("console.log('Inside Chrome context');")
Safari 浏览器

这些是 Apple Safar i浏览器特有的功能和特性。

ChromiumFirefox 驱动程序不同,safardriver 是随操作系统一起安装的。要在 Safari 上启用自动化,从终端运行以下命令:

复制代码
safaridriver --enable
参数

Safari 独有的功能可以在苹果关于 Safarihttps://developer.apple.com/documentation/webkit/about_webdriver_for_safari#2957227 页面上找到

首先启动一个 Safari 会话,如下所示:

复制代码
options = webdriver.SafariOptions()
driver = webdriver.Safari(options=options)
打开/关闭日志

与其他浏览器不同,Safari 不允许您选择日志输出位置或更改级别。一个可用的选项是关闭或打开日志。如果日志被打开,它们可以在:~/Library/ logs /com.apple.WebDriver/找到。

复制代码
service = webdriver.SafariService(enable_logging=True)
开发者工具

苹果提供了他们浏览器的开发版本。

复制代码
options = webdriver.SafariOptions()
options.use_technology_preview = True
service = webdriver.SafariService(
   executable_path='/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
)
driver = webdriver.Safari(options=options, service=service)
IE 浏览器

IE 浏览器已经停用,在此不累述;感兴趣的可以自行学习。

同步策略

也许浏览器自动化最常见的挑战是确保 web 应用程序执行特定 Selenium命令时能够得到所需的状态。这些进程通常以竞争状态结束,有时浏览器首先进入正确的状态(事情按预期工作),有时 Selenium 代码首先执行(事情不按预期工作)。

Webdriver 将控制权返回给代码之前,所有导航命令都等待基于页面加载策略的特定 readyState值(默认为 complete)。readyState 只关注 HTML 中加载的资源,但是加载的 JavaScript 资源通常会导致站点的更改,并且当代码准备执行下一个Selenium 命令时,需要与之互动的元素可能还没有出现在页面上。

类似地,在许多单页面应用中,元素被动态地添加到页面中,或者根据点击情况改变可见性。只有元素已经加载并显示在页面上,Selenium 才能与之交互。

https://www.selenium.dev/selenium/web/dynamic.html 页面为例,当 "Add a box!" 按钮点击后,则创建一个原本不存在的 "div" 元素。当单击 "Reveal a new input" 按钮时,将显示一个隐藏的文本输入框。在这两种情况下,转换都需要几秒钟。如果 Selenium 代码要单击其中一个按钮并与生成的元素交互,那么它将在该元素准备好并失败之前执行此操作。

好多人采用的第一个解决方案是添加一个 sleep 语句,将代码执行暂停一段时间。因为代码不能确切地知道它需要等待多长时间,所以当它等待时长不够时,这可能会失败。另外,如果该值设置得太高,并且在每个需要的地方都添加了 sleep 语句,那么会话的持续时间可能会变得令人望而却步。

Selenium提供了两种更好的同步机制:隐式同步策略(Implicit Waits) 和 显式同步策略(Explicit Waits)。

隐式同步策略

Selenium 有一种内置的方法来自动等待元素加载,称为"隐式等待"。隐式等待值可以通过浏览器选项中的超时功能设置,也可以通过 Webdriver 方法设置(如下所示)。

这是一个全局设置,适用于整个会话的每个元素位置调用。默认值是0,这意味着如果没有找到该元素,它将立即返回一个错误。如果设置了隐式等待,Webdriver 将在返回错误之前等待所提供值的持续时间。请注意,一旦元素被定位,Webdriver 将返回元素引用,代码将继续执行,因此较大的隐式等待值不一定会增加会话的持续时间。

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

用隐式等待来解决我们的例子是这样的:

复制代码
driver.implicitly_wait(2)
显式同步策略

显式等待是添加到代码中的循环,它在应用程序退出循环并继续执行代码中的下一个命令之前,轮询应用程序以确定特定条件是否为真。如果在指定的超时值之前没有满足条件,代码将给出一个超时错误。由于有许多方法可以使应用程序不处于期望的状态,因此显式等待是一个很好的选择,可以在需要的每个位置指定要等待的确切条件。另一个很好的特性是,默认情况下,Selenium Wait类会自动等待指定的元素存在。

定制化

可以用各种参数实例化 Wait类,这些参数将改变条件的计算方式。包括:

  • 更改代码的求值频率(轮询间隔)
  • 指定应该自动处理哪些异常
  • 更改总超时长度
  • 自定义超时消息

例如,如果默认情况下重试了元素不可交互错误,那么我们可以在执行的代码中为方法添加一个操作(我们只需要确保代码成功时返回true):

复制代码
errors = [NoSuchElementException, ElementNotInteractableException]
    wait = WebDriverWait(driver, timeout=2, poll_frequency=.2, ignored_exceptions=errors)
    wait.until(lambda _ : revealed.send_keys("Displayed") or True)

网页元素操作

文件上传

因为 Selenium 不能与文件上传对话框交互,所以它提供了一种不打开对话框就可以上传文件的方法。如果元素是类型为 file 的输入元素,则可以使用 send keys 方法发送要上传的文件的完整路径。

复制代码
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
file_input.send_keys(upload_file) # upload_file:要上传的文件的完整路径
driver.find_element(By.ID, "file-submit").click()
元素查找定位

识别 DOM 树中一个或多个特定元素的方法。

定位器是一种识别页面上元素的方法。它是传递给 Finding 元素方法的参数。SeleniumWebDriver 中的这8种传统位置定位策略提供了支持:

定位器 说明
By.CLASS_NAME 定位元素类名中包含搜索值的元素(不允许使用复合类名)
By.CSS_SELECTOR 定位元素的 cssCSS 选择器匹配的元素
By.ID 定位 ID与搜索值匹配的元素
By.NAME 查找 NAME 属性与搜索值匹配的元素
By.LINK_TEXT 定位其可见文本与搜索值匹配的锚元素
By.PARTIAL_LINK_TEXT 定位其可见文本包含搜索值的锚(A)元素。如果有多个元素匹配,则只选择第一个元素。
By.TAG_NAME 定位标记名称与搜索值匹配的元素
By.XPATH 定位与 XPath表达式匹配的元素
通过 class 属性定位

HTML 网页元素可以有属性类。我们可以在上面显示的 HTML 片段中看到一个示例。我们可以使用 Selenium 中可用的类名定位器来标识这些元素。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.CLASS_NAME, "information")
通过 CSS 选择器定位

CSS 是用于样式化 HTML 页面的语言。我们可以使用 css选择器定位器策略来识别页面上的元素。如果元素有一个 id,我们创建定位符 css = #id。否则,我们遵循的格式是 css =[attribute=value]。让我们看看上面 HTML 片段中的一个例子。我们将使用 css 为名字文本框创建定位器。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.CSS_SELECTOR, "#fname")
通过 id 定位

我们可以使用网页中元素的 ID 属性来定位它。一般来说,对于网页上的每个元素,ID 属性应该是唯一的。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.ID, "lname")
通过 name 定位

我们可以使用网页中元素的 NAME 属性来定位它。一般来说,NAME 属性对于网页上的每个元素都应该是唯一的。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.NAME, "newsletter")
通过链接的文本定位

如果我们想要定位的元素是一个链接,我们可以使用链接文本定位器在网页上识别它。链接文本是链接显示的文本

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.LINK_TEXT, "Selenium Official Page")
通过链接的部分文本定位

如果我们想要定位的元素是一个链接,我们可以使用部分链接文本定位器在网页上识别它。链接文本是链接显示的文本。我们可以将部分文本作为值传递。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")
通过 HTML 标签定位

我们可以使用 HTML TAG 本身作为定位器来识别页面上的 web 元素。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.TAG_NAME, "a")
通过 XPath 定位

可以将 HTML 文档视为 XML 文档,然后我们可以使用 xpath ,它将是遍历的路径,以到达感兴趣的元素以定位该元素。XPath 可以是绝对 XPath,它是从文档的根创建的。- /html/form/input[1]。这将返回男性单选按钮。xpath也可以是相对的。如 //input[@name='fname'],这将返回名字文本框。

复制代码
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/locators_tests/locators.html")
element = driver.find_element(By.XPATH, "//input[@value='f']")
元素的属性和方法
is_displayed

此方法用于检查所连接的元素是否显示在网页上。返回一个布尔值,如果连接的元素显示在当前浏览上下文中则返回 True,否则返回False

复制代码
driver.get("https://www.selenium.dev/selenium/web/inputs.html")

# isDisplayed
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()
is_enabled

此方法用于检查在网页上是否启用或禁用了已连接的元素。返回一个布尔值,如果连接的元素在当前浏览上下文中启用,则返回 True,否则返回 False

复制代码
is_enabled_button = driver.find_element(By.NAME, "button_input").is_enabled()
is_selected

此方法确定引用的元素是否被选中。该方法广泛用于复选框、单选按钮、输入元素和选项元素。返回一个布尔值,如果引用的元素在当前浏览上下文中被选中,则返回 True,否则返回 False

复制代码
is_selected_check = driver.find_element(By.NAME, "checkbox_input").is_selected()
tag_name

它用于获取当前浏览上下文中具有焦点的引用元素的 TagName

复制代码
tag_name_inp = driver.find_element(By.NAME, "email_input").tag_name
位置和尺寸

它用于获取被引用元素的尺寸和坐标。获取的数据体包含以下详细信息:

  • 从元素的左上角开始的 x 轴位置

  • 从元素的左上角开始的 y 轴位置

  • 元素的高度

  • 元素的宽度

    rect = driver.find_element(By.NAME, "range_input").rect

获取 css

检索当前浏览上下文中元素的指定计算样式属性的值。

复制代码
css_value = driver.find_element(By.NAME, "color_input").value_of_css_property("font-size")
获取文本

检索指定元素的呈现文本。

复制代码
text = driver.find_element(By.TAG_NAME, "h1").text
元素互动

用于操作表单控件的高级指令集。

在一个元素上只能执行5个基本命令:

  • click:点击。适用于任何元素。
  • send_keys:发送键。仅适用于文本字段和内容可编辑元素。
  • clear:清除。仅适用于文本字段和内容可编辑元素。
  • submit:提交。仅适用于表单元素。
  • select:选择。参见选择列表元素。
点击互动
复制代码
 # Navigate to URL
 driver.get("https://www.selenium.dev/selenium/web/inputs.html")

# Click on the checkbox
check_input = driver.find_element(By.NAME, "checkbox_input")
check_input.click()
发送键

元素send_keys命令将提供的键输到一个可编辑的元素中。通常,这意味着元素是具有文本类型的表单的输入元素或具有内容可编辑属性的元素。如果它不可编辑,则返回无效的元素状态错误。

复制代码
 # Handle the email input field
email_input = driver.find_element(By.NAME, "email_input")
email_input.clear()  # Clear field
    
email = "admin@localhost.dev"
email_input.send_keys(email)  # Enter text
清除

clear 命令用来重置元素的内容。这要求元素是可编辑和可重置的。通常,这意味着元素是具有 text 类型的表单的输入元素或具有content-editable 属性的元素。如果不满足这些条件,则返回无效的元素状态错误。

复制代码
email_input = driver.find_element(By.NAME, "email_input")
email_input.clear()  # Clear field
提交

Selenium 4 中,不再通过执行脚本使用单独的端点和函数来实现这一点。因此,建议不要使用这种方法,而是单击适用的表单提交按钮。

行为模拟

键盘模拟

用于与网页交互的任何键输入设备的表示形式。

只有两种操作可以用键盘完成:按下一个键和释放一个键。除了支持 ASCII 字符外,每个键盘键都有一个表示,可以按指定的顺序按下或释放。

除了常规 unicode 表示的键之外,还将 unicode 值分配给其他键盘键以供 Selenium 使用。每种语言都有自己的方式来引用这些键;完整的名单可以在这里找到。

key_down
复制代码
ActionChains(driver)\
        .key_down(Keys.SHIFT)\
        .send_keys("abc")\
        .perform()
key_up
复制代码
ActionChains(driver)\
        .key_down(Keys.SHIFT)\
        .send_keys("a")\
        .key_up(Keys.SHIFT)\
        .send_keys("b")\
        .perform()
激活元素

send_keysActions API 中的一个方便方法,它在一个操作中组合了 keyDownkeyUp 命令。执行此命令与使用元素的方法略有不同,但主要是在需要在其他操作中键入多个字符时使用。

复制代码
text_input = driver.find_element(By.ID, "textInput")
    ActionChains(driver)\
        .send_keys_to_element(text_input, "abc")\
        .perform()

以上代码表示向指定的输入框发送 abc 字符串并激活输入框。下面的代码是未指定元素而直接发送字符串并激活当前元素:

复制代码
    ActionChains(driver)\
        .send_keys("abc")\
        .perform()
复制/粘贴
复制代码
   cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL

    ActionChains(driver)\
        .send_keys("Selenium!")\
        .send_keys(Keys.ARROW_LEFT)\
        .key_down(Keys.SHIFT)\
        .send_keys(Keys.ARROW_UP)\
        .key_up(Keys.SHIFT)\
        .key_down(cmd_ctrl)\
        .send_keys("xvv")\
        .key_up(cmd_ctrl)\
        .perform()
鼠标模拟

鼠标总共有5个已定义的按钮:

  • 0 :左键(默认)
  • 1 :中间键(目前不支持)
  • 2:右键
  • 3:X1(后退)按钮
  • 4 :X2(前进)按钮
鼠标左键按下并保持

此方法结合了将鼠标移动到元素的中心和按下鼠标左键。这对于聚焦特定元素很有用。

复制代码
    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver) \
        .click_and_hold(clickable) \
        .perform()
鼠标左键按下后松开

此方法将移动到元素的中心与按下并释放鼠标左键结合起来。这也就是所谓的"点击":

复制代码
    clickable = driver.find_element(By.ID, "click")
    ActionChains(driver) \
        .click(clickable) \
        .perform()
鼠标右键点击

此方法结合了移动到元素中心和按下并释放鼠标右键(按钮2)。这也就是所谓的"右键点击"。

复制代码
    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver) \
        .context_click(clickable) \
        .perform()
鼠标后退键点击

这没有方便的方法,只是按下并释放鼠标按钮 3

复制代码
    action = ActionBuilder(driver)
    action.pointer_action.pointer_down(MouseButton.BACK)
    action.pointer_action.pointer_up(MouseButton.BACK)
    action.perform()
鼠标前进键点击

这没有方便的方法,它只是按下和释放鼠标按钮 4

复制代码
    action = ActionBuilder(driver)
    action.pointer_action.pointer_down(MouseButton.FORWARD)
    action.pointer_action.pointer_up(MouseButton.FORWARD)
    action.perform()
鼠标左键双击

此方法将移动到元素的中心与按下并释放鼠标左键两次相结合。

复制代码
    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver) \
        .double_click(clickable) \
        .perform()
鼠标移动到指定元素上

此方法将鼠标移动到元素的视图中心点。这也被称为"悬停"。注意,元素必须在视窗中,否则命令会出错。

复制代码
    hoverable = driver.find_element(By.ID, "hover")
    ActionChains(driver) \
        .move_to_element(hoverable) \
        .perform()
按相对位置移动鼠标

这些方法首先将鼠标移动到指定的原点,然后移动所提供偏移量中的像素数。注意,鼠标的位置必须在视窗(viewport)中,否则命令将出错。相对位置移动有三种情况:一种是将鼠标移动到元素的视图中心点,然后按提供的偏移量移动。

复制代码
mouse_tracker = driver.find_element(By.ID, "mouse-tracker")
    ActionChains(driver) \
        .move_to_element_with_offset(mouse_tracker, 8, 0) \
        .perform()

另外一种是通过提供的偏移量将鼠标从当前视窗(viewport)的左上角移动。

复制代码
    action = ActionBuilder(driver)
    action.pointer_action.move_to_location(8, 0)
    action.perform()

第三种是通过用户提供的偏移量将鼠标从当前位置移动。如果之前没有移动过鼠标,则该位置将位于视口的左上角。注意,滚动页面时,指针的位置不会改变。

注意,第一个参数 XXX 指定当为正数时向右移动,而第二个参数 YYY 指定当为正数时向下移动。因此 moveByOffset(30, -10)从当前鼠标位置向右移动 303030 和向上移动 101010。

复制代码
    ActionChains(driver) \
        .move_by_offset(13, 15) \
        .perform()
拖动元素

该方法首先在源元素上执行单击并按住操作,移动到目标元素的位置,然后释放鼠标。

复制代码
    draggable = driver.find_element(By.ID, "draggable")
    droppable = driver.find_element(By.ID, "droppable")
    ActionChains(driver) \
        .drag_and_drop(draggable, droppable) \
        .perform()
按相对位置拖动元素

该方法首先在源元素上执行单击并按住操作,移动到给定的偏移量,然后释放鼠标。

复制代码
    draggable = driver.find_element(By.ID, "draggable")
    start = draggable.location
    finish = driver.find_element(By.ID, "droppable").location
    ActionChains(driver) \
        .drag_and_drop_by_offset(draggable, finish['x'] - start['x'], finish['y'] - start['y']) \
        .perform()
使用手写笔

这是一种用于与网页交互的指针输入的手写笔的表示。Pen 是一种指针输入类型,具有与鼠标相同的大部分行为,但也可以具有触控笔特有的事件属性。此外,鼠标有 555 个按钮,而笔有 333 个相同的按钮状态:

  • 0 : Touch Contact(默认;相当于左键点击)
  • 2 :桶形按钮(相当于右键)
  • 5 :橡皮擦按钮(目前驱动程序不支持)

手写笔功能要求 selenium 版本至少为 4.2 版本及以上。

复制代码
    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2)\
        .pointer_up()
    action.perform()
添加指针事件属性
复制代码
    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
        .pointer_up(0)
    action.perform()
滚轮

用于与网页交互的滚轮输入设备的表示形式。要求 Selenium v4.2 版本及以上,且只能在 Chromium上使用。

滚动到元素

这是最常见的场景。与传统的 clicksend_keys方法不同,actions 类不会自动将目标元素滚动到视图中,所以如果元素不在视图中,则需要使用此方法。

这个方法接受一个web元素作为唯一参数。无论元素是在当前视屏的上方还是下方,视屏都会被滚动,这样元素的底部就会在屏幕的底部。

复制代码
 iframe = driver.find_element(By.TAG_NAME, "iframe")
    ActionChains(driver)\
        .scroll_to_element(iframe)\
        .perform()
按给定坐标值滚动

这是第二种常见的滚动场景。传入一个 xxx 值和一个 yyy 值,表示向右和向下滚动的幅度。负值分别表示向左和向上。

复制代码
    footer = driver.find_element(By.TAG_NAME, "footer")
    delta_y = footer.rect['y']
    ActionChains(driver)\
        .scroll_by_amount(0, delta_y)\
        .perform()
从一个元素滚动给定的量

这种场景实际上是上述两种方法的组合。要执行此操作,请使用 Scroll From方法,该方法接受 333 个参数。第一个表示起始点,我们将其指定为元素,第二个两个表示 xxx 和 yyy 值。

如果元素在视口之外,它将被滚动到屏幕的底部,然后页面将被提供的 xxx 和 yyy 值滚动。

复制代码
    iframe = driver.find_element(By.TAG_NAME, "iframe")
    scroll_origin = ScrollOrigin.from_element(iframe)
    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()
从带有偏移量的元素滚动

当您只需要滚动屏幕的一部分,并且它在视窗(viewport)之外时,使用此场景。或位于视窗中,并且必须滚动的屏幕部分是与特定元素的已知偏移量。

这再次使用了 Scroll From 方法,除了指定元素之外,还指定了一个偏移量来指示滚动的原点。偏移量从所提供元素的中心计算。

如果元素位于视窗之外,则首先将其滚动到屏幕底部,然后将通过向元素中心的坐标添加偏移量来确定滚动的原点,最后将根据提供的 xxx 和 yyy 值滚动页面。

请注意,如果元素中心的偏移量落在视口之外,则会导致异常。

复制代码
    footer = driver.find_element(By.TAG_NAME, "footer")
    scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()
从原点(元素)的偏移量开始滚动给定的量

最后一种场景是当您只需要滚动屏幕的一部分,并且它已经在视窗中时使用。

这再次使用了 Scroll From 方法,但是视窗被指定而不是一个元素。从当前视窗的左上角指定偏移量。确定原点后,将根据提供的 xxx 和 yyy 值滚动页面。

请注意,如果视窗左上角的偏移量落在屏幕之外,则会导致异常。

复制代码
    scroll_origin = ScrollOrigin.from_viewport(10, 10)

    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()

浏览器级交互

获取浏览器信息
获取页面标题
复制代码
title = driver.title
获取当前页面链接
复制代码
url = driver.current_url
导航操作
导航到指定地址
复制代码
driver.get("https://www.selenium.dev/selenium/web/index.html")
上一个历史访问
复制代码
driver.back()
下一个历史访问
复制代码
driver.forward()
刷新
复制代码
driver.refresh()
对话框
alert
复制代码
element = driver.find_element(By.LINK_TEXT, "See an example alert")
element.click()

wait = WebDriverWait(driver, timeout=2)
alert = wait.until(lambda d : d.switch_to.alert)
text = alert.text
alert.accept()
confirm
复制代码
element = driver.find_element(By.LINK_TEXT, "See a sample confirm")
driver.execute_script("arguments[0].click();", element)

wait = WebDriverWait(driver, timeout=2)
alert = wait.until(lambda d : d.switch_to.alert)
text = alert.text
alert.dismiss()
prompt
复制代码
element = driver.find_element(By.LINK_TEXT, "See a sample prompt")
driver.execute_script("arguments[0].click();", element)

wait = WebDriverWait(driver, timeout=2)
alert = wait.until(lambda d : d.switch_to.alert)
alert.send_keys("Selenium")
text = alert.text
alert.accept()
复制代码
driver = webdriver.Chrome()
driver.get("http://www.example.com")

# Adds the cookie into current browser context
driver.add_cookie({"name": "key", "value": "value"})
复制代码
driver = webdriver.Chrome()
driver.get("http://www.example.com")

# Adds the cookie into current browser context
driver.add_cookie({"name": "foo", "value": "bar"})

# Get cookie details with named cookie 'foo'
print(driver.get_cookie("foo"))
复制代码
driver = webdriver.Chrome()

driver.get("http://www.example.com")

driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})

# Get all available cookies
print(driver.get_cookies())
复制代码
driver = webdriver.Chrome()

driver.get("http://www.example.com")

driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})

# Delete cookie with name 'test1'
driver.delete_cookie("test1")
复制代码
driver = webdriver.Chrome()

driver.get("http://www.example.com")

driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})

# Delete all cookies
driver.delete_all_cookies()
操作 Frame

Frame是一种从同一域中的多个文档构建站点布局的方法,现在已经过时了。除非你使用的是 HTML5 之前的网页应用,否则你不太可能使用它们。iframe 允许从完全不同的域插入文档,并且仍然被广泛使用。

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

复制代码
<div id="modal">
  <iframe id="buttonframe" name="myframe"  src="https://seleniumhq.github.io">
   <button>Click here</button>
 </iframe>
</div>

如果它不是为 iframe,我们将期望点击按钮使用类似:

复制代码
# This Wont work
driver.find_element(By.TAG_NAME, 'button').click()

但是,如果 iframe 之外没有按钮,则可能会得到 no such element 错误。这是因为 Selenium 只知道顶层文档中的元素。为了与按钮交互,我们需要首先切换到框架,以类似于切换窗口的方式。WebDriver 提供了三种切换到帧的方法。下面的示例代码展示了我们如何使用一个实时的 web 示例来做到这一点。

使用 WebElement

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

复制代码
# --- Switch to iframe using WebElement ---
iframe = driver.find_element(By.ID, "iframe1")
driver.switch_to.frame(iframe)
assert "We Leave From Here" in driver.page_source

email_element = driver.find_element(By.ID, "email")
email_element.send_keys("admin@selenium.dev")
email_element.clear()
driver.switch_to.default_content()
使用 name 或者 id 操作

如果您的框架或 iframe 具有 idname 属性,则可以使用此属性。如果名称或 ID 在页面上不是唯一的,那么将切换到找到的第一个。

复制代码
# --- Switch to iframe using name or ID ---
iframe1=driver.find_element(By.NAME, "iframe1-name")  # (This line doesn't switch, just locates)
driver.switch_to.frame(iframe)
assert "We Leave From Here" in driver.page_source

email = driver.find_element(By.ID, "email")
email.send_keys("admin@selenium.dev")
email.clear()
driver.switch_to.default_content()
使用索引

也可以使用框架的索引,例如可以在 JavaScript 中使用 window.frames 进行查询。

复制代码
driver.switch_to.frame(0)
assert "We Leave From Here" in driver.page_source

要保留 iframeframeset,请切换回默认内容,如下所示:

复制代码
driver.switch_to.default_content()
assert "This page has iframes" in driver.page_source
页面打印

打印网页是一项常见的任务,无论是共享信息还是维护档案。Selenium 通过 printopoptionsPrintsPagebrowsingContext 类简化了这个过程,这些类为自动打印网页提供了灵活直观的界面。这些类使您能够配置打印首选项,例如页面布局、页边距和缩放,从而确保输出满足您的特定需求

配置页面方向

使用 getOrientation()setOrientation()方法,您可以获取/设置页面方向: PORTRAIT(纵向) 或 LANDSCAPE(横向)。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.orientation = "landscape" ## landscape or portrait
配置打印页面范围

使用 getPageRanges()setPageRanges()方法,您可以获取/设置要打印的页面范围(如"2-4")。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.page_ranges = ["1, 2, 3"] ## ["1", "2", "3"] or ["1-3"]
设置页面尺寸

使用 getPageSize()setPageSize()方法,您可以获取/设置要打印的纸张大小(如"A0","A6","Legal","小报"等)。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.page_height = 27.94  # Use page_width to assign width
设置页边距

使用 getPageMargin()setPageMargin()方法,你可以设置你想要打印的页面的边距大小即 top, bottom, left, right 边距。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.margin_top = 10
print_options.margin_bottom = 10
print_options.margin_left = 10
print_options.margin_right = 10
设置缩放

使用 getScale()setScale()方法,你可以获取/设置你想要打印的页面的比例(例如1.0是100%或默认值,0.25是25%,等等)。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.scale = 0.5 ## 0.1 to 2.0
current_scale = print_options.scale
设置背景

使用 getBackground()setBackground()方法,您可以获取/设置背景颜色和图像是否出现-布尔值为真或假。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.background = True ## True or False
设置自适应填充

使用 getShrinkToFit()setShrinkToFit()方法,您可以获取/设置页面是否将收缩到适合页面上的内容-布尔值为真或假。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
print_options.shrink_to_fit = True ## True or False
打印

配置好打印选项之后,就可以打印页面了。为此,您可以调用 print 函数,该函数生成网页的 PDF 表示形式。生成的 PDF 可以保存到本地存储以供进一步使用或分发。使用 printpage()print 命令将返回 base64 编码格式的 PDF 数据,该格式可以解码并写入所需位置的文件,使用 BrowsingContext()将返回 String

根据您选择的语言,目前可能有多种实现。例如,使用 Java ,您可以使用 BrowingContext()printpage()进行打印。两者都以PrintOptions()对象作为参数。

复制代码
driver.get("https://www.selenium.dev/")
print_options = PrintOptions()
pdf = driver.print_page(print_options)
操作浏览器
获取浏览器窗口句柄

WebDriver 不区分窗口和选项卡。如果您的站点打开了一个新的选项卡或窗口,Selenium会让您使用窗口句柄来处理它。每个窗口都有一个唯一的标识符,在单个会话中保持持久。你可以使用以下命令获取当前窗口的窗口句柄:

复制代码
driver.current_window_handle
切换浏览器窗口

单击在新窗口中打开的链接将使新窗口或选项卡集中在屏幕上,但 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:
    # Open URL
    driver.get("https://seleniumhq.github.io")

    # Setup wait for later
    wait = WebDriverWait(driver, 10)

    # Store the ID of the original window
    original_window = driver.current_window_handle

    # Check we don't have other windows open already
    assert len(driver.window_handles) == 1

    # Click the link which opens in a new window
    driver.find_element(By.LINK_TEXT, "new window").click()

    # Wait for the new window or tab
    wait.until(EC.number_of_windows_to_be(2))

    # Loop through until we find a new window handle
    for window_handle in driver.window_handles:
        if window_handle != original_window:
            driver.switch_to.window(window_handle)
            break

    # Wait for the new tab to finish loading content
    wait.until(EC.title_is("SeleniumHQ Browser Automation"))
关闭浏览器或选项卡

当你完成了一个窗口或选项卡,并且它不是浏览器中打开的最后一个窗口或选项卡时,你应该关闭它并切换回你之前使用的窗口。假设您遵循了上一节中的代码示例,那么您将把前面的窗口句柄存储在一个变量中。把这些放在一起,你会得到:

复制代码
#Close the tab or window
driver.close()

#Switch back to the old tab or window
driver.switch_to.window(original_window)
创建浏览器窗口/选项卡

创建一个新窗口(或)选项卡,并将新窗口或选项卡聚焦在屏幕上。您不需要切换到使用新窗口(或)选项卡。如果你打开了两个以上的窗口(或)选项卡,而不是新窗口,你可以在 WebDriver 可以看到的窗口或选项卡上循环,并切换到不是原来的那个。

注意:此特性适用于 Selenium 4 及更高版本。

复制代码
# Opens a new tab and switches to new tab
driver.switch_to.new_window('tab')

# Opens a new window and switches to new window
driver.switch_to.new_window('window')
获取浏览器窗口大小
复制代码
# Access each dimension individually
width = driver.get_window_size().get("width")
height = driver.get_window_size().get("height")

# Or store the dimensions and query them later
size = driver.get_window_size()
width1 = size.get("width")
height1 = size.get("height")
设置浏览器窗口大小
复制代码
driver.set_window_size(1024, 768)
获取浏览器窗口位置
复制代码
# Access each dimension individually
x = driver.get_window_position().get('x')
y = driver.get_window_position().get('y')

# Or store the dimensions and query them later
position = driver.get_window_position()
x1 = position.get('x')
y1 = position.get('y')
设置浏览器窗口位置
复制代码
driver.set_window_position(0, 0)
最大化浏览器窗口
复制代码
driver.maximize_window()
浏览器全屏
复制代码
driver.fullscreen_window()
页面截图

用于捕获当前浏览上下文的屏幕截图。WebDriver 端点截图返回 Base64 格式编码的截图。

复制代码
from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://www.example.com")

# Returns and base64 encoded string into image
driver.save_screenshot('./image.png')

driver.quit()
元素截图

用于为当前浏览上下文捕获元素的屏幕截图。WebDriver 端点截图返回 Base64 格式编码的截图。

复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

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()
执行脚本

在选定框架或窗口的当前上下文中执行 JavaScript 代码片段。

复制代码
# Stores the header element
header = driver.find_element(By.CSS_SELECTOR, "h1")

# Executing JavaScript to capture innerText of header element
driver.execute_script('return arguments[0].innerText', header)
虚拟认证

Web Authenticator 模型的表示形式。
Web 应用程序可以启用称为 Web authentication 的基于公钥的身份验证机制,以无密码的方式对用户进行身份验证。Web 身份验证定义了允许用户创建公钥凭据并将其注册到身份验证器的 api 。身份验证器可以是存储用户公钥凭证并在请求时检索它们的硬件设备或软件实体。

顾名思义,Virtual Authenticator 模拟这样的验证器进行测试。

配置

虚拟身份验证具有一组属性。这些属性在 Selenium 绑定中被映射为 VirtualAuthenticatorOptions

复制代码
options = VirtualAuthenticatorOptions()
options.is_user_verified = True
options.has_user_verification = True
options.is_user_consenting = True
options.transport = VirtualAuthenticatorOptions.Transport.USB
options.protocol = VirtualAuthenticatorOptions.Protocol.U2F
options.has_resident_key = False
添加虚拟认证器

它使用所提供的属性创建一个新的虚拟身份验证器。

复制代码
options = VirtualAuthenticatorOptions()
options.protocol = VirtualAuthenticatorOptions.Protocol.U2F
options.has_resident_key = False

# Register a virtual authenticator
driver.add_virtual_authenticator(options)
删除虚拟认证器

删除先前添加的虚拟身份验证器。

复制代码
options = VirtualAuthenticatorOptions()

# Register a virtual authenticator
driver.add_virtual_authenticator(options)

# Remove virtual authenticator
driver.remove_virtual_authenticator()
创建有状态凭据

使用给定的必需凭据参数创建常驻(有状态)凭据。

复制代码
# parameters for Resident Credential
credential_id = bytearray({1, 2, 3, 4})
rp_id = "localhost"
user_handle = bytearray({1})
privatekey = urlsafe_b64decode(BASE64__ENCODED_PK)
sign_count = 0

# create a resident credential using above parameters
resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count)
创建无状态凭据

使用给定的必需凭据参数创建常驻(无状态)凭据。

复制代码
# parameters for Non Resident Credential
credential_id = bytearray({1, 2, 3, 4})
rp_id = "localhost"
privatekey = urlsafe_b64decode(BASE64__ENCODED_PK)
sign_count = 0

# create a non resident credential using above parameters
credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count)
添加凭据

向身份验证者注册凭据。

复制代码
driver.add_credential(credential)
获取凭据

返回验证者拥有的凭据列表。

复制代码
credential_list = driver.get_credentials()
删除凭据

根据传递的凭据id从身份验证器中删除凭据。

复制代码
driver.remove_credential(credential.id)
删除所有凭据

从身份验证器中删除所有凭据。

复制代码
driver.remove_all_credentials()
设置用户验证结果状态

设置验证器在用户验证时模拟成功还是失败。

复制代码
# Create virtual authenticator options
options = VirtualAuthenticatorOptions()
options.is_user_verified = True
相关推荐
沃斯堡&蓝鸟2 小时前
DAY31 函数专题2:装饰器
python
ss2732 小时前
Executors预定义线程池-正确使用姿势
linux·开发语言·python
七夜zippoe2 小时前
Python高级数据结构深度解析:从collections模块到内存优化实战
开发语言·数据结构·python·collections·内存视图
叶子2024222 小时前
骨架点xy与 骨架点yx排序对比
python
yj15583 小时前
新房子装修好不能直接入住的原因有哪些?
python
luoluoal3 小时前
基于python的病人信息管理系统及安全策略分析(源码+文档)
python·mysql·django·毕业设计·源码
cnxy18810 小时前
围棋对弈Python程序开发完整指南:步骤1 - 棋盘基础框架搭建
开发语言·python
落叶,听雪10 小时前
河南建站系统哪个好
大数据·人工智能·python
极客小云11 小时前
【生物医学NLP信息抽取:药物识别、基因识别与化学物质实体识别教程与应用】
python·机器学习·nlp