环境搭建
- 安装:
shell
pip install selenium
- 下载驱动 Chrome: registry.npmmirror.com/binary.html...
Edge: developer.microsoft.com/zh-cn/micro...
官方文档:www.selenium.dev/zh-cn/docum...
操作元素
等待元素设置
- 隐式等待 (不推荐)
python
driver.implicitly_wait(10) # 等待10秒(推荐值)
- 作用:全局设置元素查找的最长等待时间(所有元素操作都会应用此等待)
- 适用场景:简单页面(如登录页),但不推荐在复杂项目中单独使用
- 显示等待
python
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 异常。
python
from selenium.webdriver.common.by import By
# 语法
element = driver.find_element(By.定位策略, "定位值")
参数说明:
- 第一个参数 (By.策略):指定如何查找元素(如 ID、CSS 选择器、XPath 等)。
- 第二个参数 (
"定位值"):具体的定位字符串(如 "kw" ,"//div[@id='app']")。
| 定位策略 | 代码示例 | 说明 |
|---|---|---|
| ID | By.ID, "kw" |
最快、最稳定。HTML 中 id 属性必须唯一。 |
| CSS Selector | By.CSS_SELECTOR, ".class-name" |
语法简洁,性能优秀,比 XPath 更易读。 |
| Name | By.NAME, "wd" |
常用于表单输入框,但 name 不一定唯一。 |
| XPath | By.XPATH, "//input[@id='kw']" |
最强大,可以定位任何节点(包括父子关系、文本内容),但性能稍慢且易受页面结构变化影响。 |
| Class Name | By.CLASS_NAME, "btn-submit" |
仅支持单个类名。如果元素有多个类(class="a b"),只能传 "a" 或 "b",不能传 "a b"。 |
| Tag Name | By.TAG_NAME, "input" |
通过标签名查找(如 div, a),通常用于获取页面上所有某类标签中的第一个。 |
| Link Text | By.LINK_TEXT, "登录" |
精确匹配链接的完整文本。 |
| Partial Link Text | By.PARTIAL_LINK_TEXT, "登" |
模糊匹配链接文本(包含"登"字的链接)。 |
填充表格
python
# 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
对元素操作、判断、提取
- 此方法用于检查连接的元素是否正确显示在网页上. 返回一个
Boolean值, 如果连接的元素显示在当前的浏览器上下文中,则为True,否则返回false。
python
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()
- 此方法用于检查所连接的元素在网页上是启用还是禁用状态。 返回一个布尔值,如果在当前浏览上下文中是 启用 状态,则返回 true,否则返回 false。
python
is_enabled_button = driver.find_element(By.NAME, "button_input").is_enabled()
- 此方法确认相关的元素是否 已选定,常用于复选框、单选框、输入框和选择元素中。该方法返回一个布尔值,如果在当前浏览上下文中 选择了 引用的元素,则返回 True,否则返回 False。
python
is_selected_check = driver.find_element(By.NAME, "checkbox_input").is_selected()
- 此方法用于获取在当前浏览上下文中具有焦点的被引用元素的TagName。
python
tag_name_inp = driver.find_element(By.NAME, "email_input").tag_name
- 用于获取参照元素的尺寸和坐标。提取的数据主体包含以下详细信息:元素左上角的X轴位置,元素左上角的y轴位置, 元素的高度, 元素的宽度
python
rect = driver.find_element(By.NAME, "range_input").rect
assert rect["x"] == 10
- 获取特定元素渲染后的文本内容。
python
text = driver.find_element(By.TAG_NAME, "h1").text
- 获取与 DOM 属性关联的运行时的值。 它返回与该元素的 DOM 特性或属性关联的数据。
python
email_txt = driver.find_element(By.NAME, "email_input")
value_info = email_txt.get_attribute("value")
文件上传
由于 Selenium 不能与文件上传对话框交互,因此它提供了一种无需打开对话框即可上传文件的方法。 如果该元素是一个类型为 file 的 input 元素,则可以使用 send keys 方法发送将要上传文件的完整路径。
python
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 只知道顶层文档中的元素。为了与按钮进行交互,我们需要首先切换到框架, 这与切换窗口的方式类似。
- 使用索引,还可以使用frame的索引, 例如可以使用JavaScript中的
window.frames进行查询.
python
driver.switch_to.frame(0)
- 离开框架。离开 iframe 或 frameset,切换回默认内容,如下所示:
python
driver.switch_to.default_content()
窗口
- 切换窗口或标签页 单击在<a href="seleniumhq.github.io"target="_blank">新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。 如果只有两个选项卡或窗口被打开,并且你知道从哪个窗口开始, 则你可以遍历 WebDriver, 通过排除法可以看到两个窗口或选项卡,然后切换到你需要的窗口或选项卡。
python
# 存储原始窗口的 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)
- 创建新窗口(或)新标签页并且切换 创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。
python
# 打开新标签页并切换到新标签页
driver.switch_to.new_window('tab')
# 打开一个新窗口并切换到新窗口
driver.switch_to.new_window('window')
- 全屏窗口 填充整个屏幕,类似于在大多数浏览器中按下 F11。
python
driver.fullscreen_window()
- 最大化窗口 扩大窗口。对于大多数操作系统,窗口将填满屏幕,而不会阻挡操作系统自己的菜单和工具栏。
python
driver.maximize_window()
Cookie
- 添加
python
# 将 Cookie 添加到当前浏览器上下文
driver.add_cookie({"name": "key", "value": "value"})
- 获得cookie
python
driver.get_cookies()
- 删除cookie
python
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属性接受以下两种参数作为指令
- Strict:当sameSite属性设置为 Strict, cookie不会与来自第三方网站的请求一起发送。
- Lax:当您将cookie sameSite属性设置为 Lax, cookie将与第三方网站发起的GET请求一起发送。
python
driver.add_cookie({"name": "foo", "value": "value", "sameSite": "Strict"})
driver.add_cookie({"name": "foo1", "value": "value", "sameSite": "Lax"})