Selenium笔记

5 阅读7分钟

环境搭建

  1. 安装:
pip install selenium
  1. 下载驱动 Chrome: registry.npmmirror.com/binary.html…

Edge: developer.microsoft.com/zh-cn/micro…

官方文档:www.selenium.dev/zh-cn/docum…

操作元素

等待元素设置

  1. 隐式等待 (不推荐)
driver.implicitly_wait(10)  # 等待10秒(推荐值)
  • 作用:全局设置元素查找的最长等待时间(所有元素操作都会应用此等待)
  • 适用场景:简单页面(如登录页),但不推荐在复杂项目中单独使用
  1. 显示等待
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.common.by import By

# 等待10秒,直到"登录按钮"可见 
login_button = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, "login-btn")))

代码整体结构拆解:

A. 初始化等待对象,WebDriverWait(driver, 10):创建一个“计时器”,最大等待时间为 10秒。

B. 触发等待动作 ,.until(...):告诉计时器:“一直等到括号里的条件满足为止”。

C. 定义等待条件,EC.visibility_of_element_located(...):具体的条件:元素必须存在且可见(不仅仅是存在于HTML中)。

D. 定位目标元素 ,(By.ID, "login-btn"):告诉 Selenium 去找哪个元素(通过 ID 为 login-btn 的属性)。

E. 接收返回值,login_button = ...:如果等待成功,将找到的元素对象赋值给变量 login_button,供后续使用(如 .click())。如果未等到,就抛异常。

Selenium 提供了多种等待条件:

  • presence_of_element_located(存在即可):只要 HTML 里有这个标签就算成功。 风险:元素可能还在加载动画中,或者被 CSS 隐藏了 (display: none)。此时如果立刻去 .click(),会报错 ElementNotInteractableException

  • visibility_of_element_located (存在且可见) :不仅要求 HTML 里有,还要求元素对用户可见(能看见,且能交互)。 优势:这是最安全的等待方式,确保元素准备好被点击或输入了。

  • element_to_be_clickable(存在、可见且可点击):比上面更严格,还要求元素没有被其他元素遮挡(Overlay),且 enabled 属性为真。 场景:专门用于点击按钮前。

  • driver.switch_to在网页自动化中,浏览器可能同时打开多个标签页,或者页面中嵌套了多个 <iframe>(内嵌框架)。默认情况下,Selenium 只能操作当前聚焦的窗口或框架。如果你想操作其他窗口或 iframe 里的元素,必须先使用 driver.switch_to 切换“焦点”。

find_element

find_element用于在网页中定位并返回单个 Web 元素。如果找到匹配的元素,它返回一个 WebElement 对象;如果找不到,它会抛出 NoSuchElementException 异常。

from selenium.webdriver.common.by import By 
# 语法 
element = driver.find_element(By.定位策略, "定位值")

参数说明:

  • 第一个参数 (By.策略):指定如何查找元素(如 ID、CSS 选择器、XPath 等)。
  • 第二个参数 ("定位值"):具体的定位字符串(如 "kw" ,"//div[@id='app']")。
定位策略代码示例说明
IDBy.ID, "kw"最快、最稳定。HTML 中 id 属性必须唯一。
CSS SelectorBy.CSS_SELECTOR, ".class-name"语法简洁,性能优秀,比 XPath 更易读。
NameBy.NAME, "wd"常用于表单输入框,但 name 不一定唯一。
XPathBy.XPATH, "//input[@id='kw']"最强大,可以定位任何节点(包括父子关系、文本内容),但性能稍慢且易受页面结构变化影响。
Class NameBy.CLASS_NAME, "btn-submit"仅支持单个类名。如果元素有多个类(class="a b"),只能传 "a""b",不能传 "a b"
Tag NameBy.TAG_NAME, "input"通过标签名查找(如 div, a),通常用于获取页面上所有某类标签中的第一个。
Link TextBy.LINK_TEXT, "登录"精确匹配链接的完整文本。
Partial Link TextBy.PARTIAL_LINK_TEXT, "登"模糊匹配链接文本(包含“登”字的链接)。

填充表格

# 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

对元素操作、判断、提取

  1. 此方法用于检查连接的元素是否正确显示在网页上. 返回一个 Boolean 值, 如果连接的元素显示在当前的浏览器上下文中,则为True,否则返回false。
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()
  1. 此方法用于检查所连接的元素在网页上是启用还是禁用状态。 返回一个布尔值,如果在当前浏览上下文中是 启用 状态,则返回 true,否则返回 false。
is_enabled_button = driver.find_element(By.NAME, "button_input").is_enabled()
  1. 此方法确认相关的元素是否 已选定,常用于复选框、单选框、输入框和选择元素中。该方法返回一个布尔值,如果在当前浏览上下文中 选择了 引用的元素,则返回 True,否则返回 False。
is_selected_check = driver.find_element(By.NAME, "checkbox_input").is_selected()
  1. 此方法用于获取在当前浏览上下文中具有焦点的被引用元素的TagName。
tag_name_inp = driver.find_element(By.NAME, "email_input").tag_name
  1. 用于获取参照元素的尺寸和坐标。提取的数据主体包含以下详细信息:元素左上角的X轴位置,元素左上角的y轴位置, 元素的高度, 元素的宽度
rect = driver.find_element(By.NAME, "range_input").rect
assert rect["x"] == 10
  1. 获取特定元素渲染后的文本内容。
text = driver.find_element(By.TAG_NAME, "h1").text
  1. 获取与 DOM 属性关联的运行时的值。 它返回与该元素的 DOM 特性或属性关联的数据。
email_txt = driver.find_element(By.NAME, "email_input")
value_info = email_txt.get_attribute("value")

文件上传

由于 Selenium 不能与文件上传对话框交互,因此它提供了一种无需打开对话框即可上传文件的方法。 如果该元素是一个类型为 file 的 input 元素,则可以使用 send keys 方法发送将要上传文件的完整路径。

def test_uploads(driver):
    driver.get("https://the-internet.herokuapp.com/upload")
    upload_file = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "..", "selenium-snapshot.png"))

    file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
    file_input.send_keys(upload_file)
    driver.find_element(By.ID, "file-submit").click()

Frames

如果 iframe 之外没有按钮,那么您可能会得到一个 _no such element无此元素 的错误。 这是因为 Selenium 只知道顶层文档中的元素。为了与按钮进行交互,我们需要首先切换到框架, 这与切换窗口的方式类似。

  1. 使用索引,还可以使用frame的索引, 例如可以使用JavaScript中的 window.frames进行查询.
driver.switch_to.frame(0)
  1. 离开框架。离开 iframe 或 frameset,切换回默认内容,如下所示:
driver.switch_to.default_content()

窗口

  1. 切换窗口或标签页 单击在<a href=“seleniumhq.github.io"target="_blank”>新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。 如果只有两个选项卡或窗口被打开,并且你知道从哪个窗口开始, 则你可以遍历 WebDriver, 通过排除法可以看到两个窗口或选项卡,然后切换到你需要的窗口或选项卡。
# 存储原始窗口的 ID
original_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

#关闭标签页或窗口
driver.close()
#切回到之前的标签页或窗口
driver.switch_to.window(original_window)
  1. 创建新窗口(或)新标签页并且切换 创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。
# 打开新标签页并切换到新标签页
driver.switch_to.new_window('tab')
# 打开一个新窗口并切换到新窗口
driver.switch_to.new_window('window')
  1. 全屏窗口 填充整个屏幕,类似于在大多数浏览器中按下 F11。
driver.fullscreen_window()
  1. 最大化窗口 扩大窗口。对于大多数操作系统,窗口将填满屏幕,而不会阻挡操作系统自己的菜单和工具栏。
driver.maximize_window()

Cookie

  • 添加
# 将 Cookie 添加到当前浏览器上下文
driver.add_cookie({"name": "key", "value": "value"})
  • 获得cookie
driver.get_cookies()
  • 删除cookie
driver.add_cookie({"name": "test1", "value": "cookie1"})
# Delete cookie with name 'test1'
driver.delete_cookie("test1")
# Delete all cookies
driver.delete_all_cookies()
  • Same-Site Cookie属性 此属性允许用户引导浏览器控制cookie, 是否与第三方站点发起的请求一起发送. 引入其是为了防止CSRF(跨站请求伪造)攻击.Same-Site cookie属性接受以下两种参数作为指令
  1. Strict:当sameSite属性设置为 Strict, cookie不会与来自第三方网站的请求一起发送。
  2. Lax:当您将cookie sameSite属性设置为 Lax, cookie将与第三方网站发起的GET请求一起发送。
driver.add_cookie({"name": "foo", "value": "value", "sameSite": "Strict"})
driver.add_cookie({"name": "foo1", "value": "value", "sameSite": "Lax"})