文章目录

浏览器自动化,为何90%的Python开发者最后都选了它
第一部分:背景——为什么我要让浏览器自己动起来
在日常测试、数据采集、自动化报表等场景中,你是否需要:
- 每天登录后台点 30 次按钮下载 Excel?
- 在 100 个商品页间来回跳转截图?
- 模拟真实用户操作验证前端交互?
纯 HTTP 请求库(requests
、aiohttp
)无法执行 JavaScript,也就无法与动态网页交互。
于是,Selenium 诞生了:它通过驱动真实的浏览器,让你用 Python 代码“代替”人类的鼠标和键盘,完成任何可视化操作。接下来,就让我们一起拆解这把“瑞士军刀”。
第二部分:Selenium 是什么
一句话:Selenium 是一个跨语言、跨浏览器的 Web 自动化框架。
- 提供统一的 WebDriver API(Python 端对应库名:
selenium
) - 支持 Chrome、Edge、Firefox、Safari 等主流浏览器
- 既能做端到端测试,也能做爬虫、RPA(机器人流程自动化)
第三部分:一行命令装好它
Selenium 是第三方库,需要额外下载浏览器驱动。以 Chrome 为例:
# 1. 安装 Python 包
pip install selenium==4.*
# 2. 安装与本地 Chrome 版本匹配的驱动
# 方案 A:手工下载 chromedriver 并解压到 PATH
# 方案 B:让 selenium-manager 自动帮你(v4.6+ 内置)
如果你看到
selenium.common.exceptions.SessionNotCreatedException
,99% 是驱动版本与浏览器版本不匹配,重新下载即可。
第四部分:5 个最常用的 API,一行一行拆给你看
1. 启动浏览器
from selenium import webdriver
driver = webdriver.Chrome() # 1. 打开本地 Chrome 浏览器
driver.maximize_window() # 2. 窗口最大化,方便观察
第 1 行:如果系统 PATH 里有
chromedriver
,会自动调用;否则会触发内置下载。
第 2 行:最大化后可减少元素被遮挡导致的ElementNotInteractableException
。
2. 访问网页并等待
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.get("https://example.com") # 1. 打开页面
wait = WebDriverWait(driver, 10) # 2. 最多等 10 秒
login_btn = wait.until(
EC.element_to_be_clickable((By.ID, "login"))
) # 3. 等到 id=login 的按钮可点击为止
WebDriverWait
+expected_conditions
是 Selenium 的“智能等待”,避免写死time.sleep()
。
3. 定位元素
username = driver.find_element(By.CSS_SELECTOR, "input[name='user']")
password = driver.find_element(By.XPATH, "//input[@type='password']")
By.CSS_SELECTOR
语法简洁,优先使用;复杂定位再用By.XPATH
。
4. 输入与点击
username.send_keys("admin") # 1. 填充用户名
password.send_keys("123456") # 2. 填充密码
login_btn.click() # 3. 点击登录
send_keys
接受字符串或可迭代按键(Keys.ENTER、Keys.TAB 等)。
5. 截图并关闭
driver.save_screenshot("dashboard.png") # 1. 当前页面截图
driver.quit() # 2. 关闭浏览器并释放资源
使用
quit()
而非close()
,确保驱动进程彻底退出。
第五部分:5 个真实场景,完整代码逐行解析
场景 1:自动登录并下载报表
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
driver = webdriver.Chrome()
driver.get("https://demo.reports.com/login")
# 登录
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
).send_keys("demo")
driver.find_element(By.ID, "password").send_keys("demo123")
driver.find_element(By.ID, "loginBtn").click()
# 进入报表页面
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.LINK_TEXT, "Monthly Report"))
).click()
# 下载
download = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button[title='Export']"))
)
download.click() # 触发下载
# 等待文件出现(Chrome 默认下载目录)
download_path = "/Users/xxx/Downloads/monthly_report.xlsx"
WebDriverWait(driver, 30).until(lambda d: os.path.exists(download_path))
driver.quit()
逐行说明见注释,核心思路:等待→操作→再等待→断言文件落地。
场景 2:无限滚动抓取微博
driver.get("https://weibo.com/search")
search_box = driver.find_element(By.CSS_SELECTOR, "input[placeholder='搜索']")
search_box.send_keys("Python\n") # \n 相当于按回车
# 循环滚动到底
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
import time; time.sleep(2) # 简单等待,生产可用 WebDriverWait
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# 抓取所有可见微博
cards = driver.find_elements(By.CSS_SELECTOR, ".card-wrap")
for c in cards:
print(c.text)
execute_script
允许运行原生 JavaScript,处理“无限滚动”这类动态加载页面。
场景 3:自动填写 100 份表单
利用 pandas
读 Excel,循环填充:
import pandas as pd
df = pd.read_excel("students.xlsx")
driver.get("https://school.com/form")
for _, row in df.iterrows():
driver.find_element(By.NAME, "name").send_keys(row["name"])
driver.find_element(By.NAME, "age").send_keys(str(row["age"]))
driver.find_element(By.NAME, "submit").click()
WebDriverWait(driver, 10).until(
EC.text_to_be_present_in_element((By.TAG_NAME, "h3"), "成功")
)
driver.get("https://school.com/form") # 重新打开空白表单
场景 4:跨浏览器兼容性冒烟测试
browsers = ["Chrome", "Firefox", "Edge"]
for b in browsers:
driver = getattr(webdriver, b)()
driver.get("https://app.com")
try:
assert "Dashboard" in driver.title
print(f"{b} 正常")
except AssertionError:
print(f"{b} 异常")
finally:
driver.quit()
使用
getattr(webdriver, b)()
一行代码动态启动不同浏览器。
场景 5:与 unittest 集成做 CI
import unittest
class TestLogin(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def test_login_success(self):
self.driver.get("https://app.com/login")
# 省略定位与断言...
self.assertIn("Dashboard", self.driver.title)
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
unittest.main()
setUp/tearDown
保证每条用例都有干净的浏览器环境,可无缝接入 Jenkins/GitHub Actions。
第六部分:3 个常见 Bug 与急救方案
Bug 1:NoSuchElementException
错误信息
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"#missing"}
原因与解决
- 元素在
<iframe>
里:先driver.switch_to.frame("frameName")
- 页面未加载完:用
WebDriverWait
而不是time.sleep(1)
碰运气
Bug 2:ElementNotInteractableException
错误信息
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
原因与解决
- 被浮层遮挡:滚动到可见区域
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).scroll_to_element(elem).perform()
- 尝试
elem.click()
失败时,可改用ActionChains(driver).move_to_element(elem).click().perform()
Bug 3:StaleElementReferenceException
错误信息
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is no longer attached to the DOM
原因与解决
DOM 刷新后引用失效;重新定位即可:
# 错误写法
rows = driver.find_elements(By.TAG_NAME, "tr")
for r in rows:
r.click() # 点击后页面刷新,下一轮循环 r 已失效
# 正确写法
for i in range(len(driver.find_elements(By.TAG_NAME, "tr"))):
driver.find_elements(By.TAG_NAME, "tr")[i].click()
第七部分:总结
Selenium = 浏览器 + Python,让你“所见即可控”。
- 入门极快:pip 一行、API 直观
- 功能极全:测试、爬虫、RPA 通吃
- 社区极大:Stack Overflow 10w+ 答案,基本搜得到
下一步?
- 想加速 → 换成无头模式
--headless=new
- 想并发 → 用 Selenium Grid 或 Docker 集群
- 想更稳 → 搭配 Page Object Model + pytest 打造企业级测试框架
现在,打开终端,输入 pip install selenium
,让你的浏览器自己动起来吧!
如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!