打开与关闭页面
演示浏览器生命周期管理的 三个核心动作:启动 → 打开页面 → 关闭/退出。看似简单,但多标签、异常中断等场景下有诸多细节。
三个 API 的区别:
driver.get(url):会阻塞,直到浏览器 load 事件触发才返回——此时 HTML 解析完成<html> <head> <title> <body> <h1> 逐个读入<h1>标题</h1> → DOM 里多了一个 h1 节点<img src="a.jpg"> → DOM 里多了一个 img 节点DOMContentLoaded ← 这就是"HTML 解析完成"window.load ← driver.get() 等的就是这个<img src="..."> 图片、<iframe src="..."> 子页面、<link href="..."> CSS、<script src="..."> 同步 JS、<video src="...">/<audio src="..."> 媒体文件)加载完毕。注意它等的是 window.load 而非 DOMContentLoaded。⚠️ 关键盲区:driver.get() 不等异步加载!
时间线:
0ms HTML 开始解析
500ms DOMContentLoaded 触发(HTML 解析完,图片还在下)
1500ms window.load 触发 ← driver.get() 在这里返回
1600ms JS 发 fetch('/api/list') ← 异步请求,get() 没等
2000ms fetch 返回,React 渲染列表 ← 动态 DOM,get() 没等
2500ms 列表渲染完成 ← 需用 WebDriverWait 等待!
load 事件不包含:fetch/AJAX 异步请求、React/Vue/Angular 框架渲染、懒加载(loading="lazy")、SPA 客户端路由跳转、setTimeout 定时器逻辑。driver.get() 返回后页面上的元素可能还没出现,必须用显式等待补位。driver.close():只关当前标签,其他标签继续,driver 仍可用driver.quit():关掉所有标签 + 杀掉 chromedriver 进程,driver 不可再用⚠️ 重要提醒:脚本里忘了写 driver.quit(),任务管理器会残留 chromedriver 进程,长期积累会吃光内存。建议用 try/finally 保证无论成功失败都执行 quit()。
get、close、quit 三个 API 覆盖完整生命周期。close() 不关浏览器进程,多标签场景下别用它收尾 |
quit() 测试结束务必调用,否则残留进程会吃内存
driver.get("https://xxx") 打开指定网址(https://autotest-505.pages.dev/,点击网址在同一浏览器窗口打开新标签页)driver.close() 关闭当前页签driver.quit() 退出整个浏览器(所有页签)
# ① 启动 Chrome 浏览器 from selenium import webdriver from selenium.webdriver.common.by import By import psutil, time # 进程对比用,需先 pip install psutil # 采集 chrome / chromedriver 进程 PID 集合的辅助函数 def procs(): return {p.pid for p in psutil.process_iter(["name"]) if p.info["name"] in ("chrome.exe", "chromedriver.exe")} _pids = procs() # 启动前基线,排除你自己开着的 Chrome driver = webdriver.Chrome() # ② 打开演示页面(此时只有这一个标签页) driver.get("https://autotest-505.pages.dev/browser_op_tech_sections/open_close_tech.html") print("启动后新增进程:", procs() - _pids) # chromedriver.exe + 若干 chrome.exe # ③ 点击“对应 API”区域中的 https://autotest-505.pages.dev/ 链接 # 该链接 target="_blank",点击后会在【同一浏览器窗口】里新开一个标签页 # 注意:点击后 driver 的焦点仍停留在原标签页,这里不做标签页切换 driver.find_element(By.CSS_SELECTOR, 'a[href="https://autotest-505.pages.dev/"]').click() time.sleep(1) # 等新标签页进程稳定 print("点击后新增进程:", procs() - _pids) # 新标签页触发 Chrome 多进程架构创建渲染进程(也可能复用) # ④ close():只关闭 driver 当前所在标签页,另一个不受影响;用 3 个信号对比(和 quit 后三行完全镜像) driver.close() print("close 后残留进程:", procs() - _pids) # 非空集合:chrome/chromedriver 都还活着 print("chromedriver 进程状态:", driver.service.process.poll()) # None:进程仍在运行(未退出) print("驱动还能连接吗:", driver.service.is_connectable()) # True:会话仍存活 # ⑤ quit():关闭所有剩余标签页并退出浏览器进程(无需先切换标签);用 3 个确定性信号佐证 driver.quit() time.sleep(1) # 等系统回收进程 print("quit 后残留进程:", procs() - _pids) # set():chrome/chromedriver 全部退出 print("chromedriver 退出码:", driver.service.process.poll()) # 0:驱动进程已正常结束 print("驱动还能连接吗:", driver.service.is_connectable()) # False:driver 已释放 # 注意:Selenium 4 的 quit() 不会把 driver.session_id 置空,不要用它判断会话是否结束
| 因素 | 本地 | CI/CD 云服务器 |
| 网络 | 专线稳定 | 数据中心共享,偶发抖动 |
| CPU | 独占 | 多租户,可能被抢占 |
| 浏览器缓存 | 有 | 没有(每次全新启动) |
| 页面加载速度 | 有缓存,秒出 | 全量下载,慢 2~5 倍 |
| 并发任务 | 只跑你这一份 | 可能几十上百个同时抢资源 |
"A session has an associated session implicit wait timeout that specifies a time to wait for the implicit element location strategy"implicit=0.5s → 驱动最多等待 500ms 后必须放弃
→ 驱动在一次 findElement / findElements 调用中,最多愿意等待的总时间即为该值,不得超时。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
def test_polling(d, delay):
d.implicitly_wait(2)
d.get('about:blank')
d.execute_script(f"setTimeout(()=>{{document.body.innerHTML='t'}},{delay})")
t0 = time.perf_counter()
try:
cost = (time.perf_counter() - t0) * 1000
print(f"delay={delay:4d} 耗时={cost:6.0f} 差值={cost-delay:+5.0f}")
except: print(f"delay={delay} 超时")
driver = webdriver.Chrome()
for delay in range(10, 1550, 50): # 50ms 步进,覆盖 10~1500ms
test_polling(driver, delay)
driver.quit()
最坏 = implicit × (explicit超时 / pollFreq)try: find_element ... except NoSuchElementException:| 值 | 兜底窗口 (规范定义) |
叠加成本 explicit=15s |
白等 10次不存在 |
依据类型 | 推荐 |
| 不设(=0) | 0ms | 0 秒 | 0 秒 | 规范 | 最严谨 |
| 1s | 1000ms | 30 秒 | 10 秒 | 经验+权衡 | 默认推荐 |
| 0.5s | 500ms | 15 秒 | 5 秒 | 经验+权衡 | 确认页面 <500ms |
| 2s | 2000ms | 60 秒 | 20 秒 | 代价太大 | 谨慎 |
| ≥5s | ≥5000ms | 150 秒+ | 50 秒+ | 爆炸 | ❌ 绝对避免 |