你有没有想过,让程序替你打开浏览器、填表单、点按钮、截个图,然后自动关掉?这就是 Selenium 干的事。
很多教程一上来就讲"自动化测试"、"pytest 框架"、"Page Object Model",但其实大多数人第一次接触 Selenium,不是为了做测试,而是想写一个自动化脚本:自动签到、自动抢票、自动采集数据。
这篇文章就从这个角度出发,带你用最短的时间跑起来第一个 Selenium 脚本。如果你之后想了解怎么让 Selenium 不被网站检测到,可以看我们的进阶篇(即将发布)。
Selenium 是一个开源的浏览器自动化工具,它可以用代码控制 Chrome、Firefox、Edge 等主流浏览器,模拟真实用户的操作。
和直接用 requests 库发 HTTP 请求不同,Selenium 会启动一个真实的浏览器,所以它能处理:
| 场景 | requests 能做吗 | Selenium 能做吗 |
|---|---|---|
| 获取静态 HTML 页面 | ✅ | ✅ |
| 处理 JavaScript 动态渲染的内容 | ❌ | ✅ |
| 填写表单、点击按钮 | ❌ | ✅ |
| 处理验证码弹窗 | ❌ | ✅ |
| 截图保存页面 | ❌ | ✅ |
| 在没有屏幕的服务器上运行 | ✅ | ✅(无头模式) |
简单来说:如果一个网页需要你"像人一样操作"才能拿到数据或完成任务,那就用 Selenium。
Selenium 需要一个真实的浏览器来驱动。直接去 Chrome 官网 下载安装,安装在默认路径就行。
如果是 Linux 服务器没有图形界面,用命令行安装:
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install -y ./google-chrome-stable_current_amd64.deb
💡 如果你的 Chrome 装在了非默认路径(比如 D 盘),Selenium 会找不到它,需要在代码里手动指定:
options.binary_location = r"D:\...\chrome.exe"。后面的代码示例会讲到怎么配置options。
需要 Python 3.8+(推荐 3.10 以上),然后装两个包:
pip install selenium webdriver-manager
selenium 是核心库,webdriver-manager 可以帮你自动下载和管理 ChromeDriver,不用自己去官网找版本对应的驱动文件。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.baidu.com")
print(driver.title) # 输出:百度一下,你就知道
driver.quit()
运行后如果弹出了 Chrome 窗口,打开了百度页面,然后自动关闭,说明环境没问题。
来写一个稍微有用点的东西:自动打开一个网页,等页面加载完成后截一张图保存下来。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time
# 配置 Chrome
options = Options()
options.add_argument("--window-size=1920,1080") # 设置窗口大小
# 启动浏览器
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
# 打开目标网页
driver.get("https://www.leapya.com")
# 等待页面加载
time.sleep(3)
# 截图保存
driver.save_screenshot("screenshot.png")
print("截图已保存为 screenshot.png")
# 关闭浏览器
driver.quit()
运行后你会在当前目录下看到一张 screenshot.png,就是网页的完整截图。
Selenium 的 API 很多,但日常写脚本最常用的就这些:
要操作网页上的按钮、输入框等元素,首先得"找到"它。Selenium 提供了多种定位方式:
from selenium.webdriver.common.by import By
# 通过 ID 定位(最推荐,速度快且唯一)
element = driver.find_element(By.ID, "username")
# 通过 CSS 选择器定位(灵活,前端同学最熟悉)
element = driver.find_element(By.CSS_SELECTOR, "input.login-input")
# 通过 XPath 定位(功能最强,能处理复杂结构)
element = driver.find_element(By.XPATH, "//input[@name='password']")
# 通过文本内容定位链接
element = driver.find_element(By.LINK_TEXT, "登录")
| 操作 | 代码 | 说明 |
|---|---|---|
| 输入文字 | element.send_keys("hello") | 模拟键盘输入 |
| 点击 | element.click() | 模拟鼠标点击 |
| 清空输入框 | element.clear() | 清除已有内容 |
| 获取文本 | element.text | 获取元素的可见文本 |
| 获取属性 | element.get_attribute("href") | 获取 HTML 属性值 |
| 截图 | driver.save_screenshot("pic.png") | 截取整个页面 |
| 执行 JS | driver.execute_script("alert('hi')") | 执行 JavaScript 代码 |
| 切换 iframe | driver.switch_to.frame("frame_id") | 进入 iframe 内部 |
| 获取当前 URL | driver.current_url | 获取当前页面地址 |
新手最常踩的坑就是:页面还没加载完,代码就去找元素,结果报 NoSuchElementException。
不要用 time.sleep() 硬等,用显式等待:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 最多等 10 秒,直到 ID 为 "submit" 的按钮出现
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "submit"))
)
button.click()
这样写的好处是:元素一出现就立刻操作,不会浪费时间;如果 10 秒内都没出现,才会报错。
这是本文的重点,也是大多数 Selenium 入门教程不会讲到的。
如果你想让脚本在云服务器、Docker 容器或者 GitHub Actions 上运行,服务器是没有显示器的,直接启动 Chrome 会报错。这时候就需要无头模式(Headless Mode),让 Chrome 在后台运行,不弹出任何窗口。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
options = Options()
# 核心:启用无头模式
options.add_argument("--headless=new")
# 以下参数在服务器环境中建议都加上
options.add_argument("--no-sandbox") # Docker/CI 环境必须
options.add_argument("--disable-dev-shm-usage") # 防止共享内存不足导致崩溃
options.add_argument("--disable-gpu") # 服务器没有 GPU
options.add_argument("--window-size=1920,1080") # 必须设置!否则默认窗口很小
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
driver.get("https://www.baidu.com")
print(driver.title)
driver.save_screenshot("headless_screenshot.png")
driver.quit()
| 注意点 | 说明 |
|---|---|
| 必须设置窗口大小 | 无头模式默认窗口可能只有 800×600,很多元素会因为页面布局变形而无法点击 |
用 --headless=new | Chrome 109+ 推荐用这个参数,比旧的 --headless 行为更接近真实浏览器 |
| 截图是你的调试利器 | 看不到浏览器界面,出问题时第一件事就是截图看当前页面状态 |
| 内存管理 | --disable-dev-shm-usage 在 Docker 和 GitHub Actions 中几乎是必须的,否则容易 OOM 崩溃 |
💡 你可能还听说过 Xvfb(虚拟显示器) 这个方案,它是更早期的做法,需要额外安装软件。现在
--headless=new已经是推荐方案,新项目直接用无头模式就行。
我们的 Rainyun-Qiandao 雨云签到项目 就是在 GitHub Actions 上用无头模式跑 Selenium 的。如果你想看一个完整的生产级项目长什么样,可以参考它的源码。
把前面学到的东西串起来,写一个自动填写登录表单的脚本:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
# 初始化(无头模式)
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1920,1080")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
try:
# 1. 打开登录页面
driver.get("https://example.com/login")
# 2. 等待用户名输入框出现
username_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
)
# 3. 输入用户名和密码
username_input.send_keys("your_username")
password_input = driver.find_element(By.ID, "password")
password_input.send_keys("your_password")
# 4. 点击登录按钮
login_button = driver.find_element(By.ID, "login-submit")
login_button.click()
# 5. 等待登录完成(判断页面跳转或元素变化)
WebDriverWait(driver, 10).until(
EC.url_contains("/dashboard")
)
print("登录成功!当前页面:", driver.current_url)
driver.save_screenshot("login_success.png")
except Exception as e:
print(f"出错了:{e}")
driver.save_screenshot("error.png") # 出错时截图,方便排查
finally:
driver.quit()
这个模板的核心模式是:try-except-finally + 出错截图。在无头模式下你看不到浏览器,出错时的截图就是你唯一的调试线索。
到这里你已经能用 Selenium 完成基本的浏览器自动化了。但如果你试着用它去访问一些有反爬机制的网站,你可能会发现:脚本被拦截了,或者行为和手动操作时完全不同。
这是因为很多网站会检测你的浏览器是不是由 Selenium 驱动的,它们检查的东西包括:
navigator.webdriver 属性是否为 true怎么绕过这些检测?这就是下一篇文章要讲的内容了。
📖 下一篇预告:《Python Selenium 反检测指南:如何绕过网站的自动化检测》,我们会详细讲解 stealth.js 注入、浏览器指纹伪装、undetected-chromedriver 等反检测技术。敬请期待。
如果你想看一个把 Selenium 自动化、无头模式、反检测、验证码识别全部集成在一起的真实项目,推荐看看我们的开源项目:
这个项目用到了本文讲的所有技术,外加 ddddocr 验证码识别、OpenCV 图像匹配等进阶功能。详细的技术解析见:《雨云签到验证码怎么破?2026最新自动识别方案》
⚠️ 免责声明:Selenium 浏览器自动化技术本身是合法的开发工具,广泛应用于自动化测试和数据采集领域。但请注意遵守目标网站的服务条款和 robots.txt 规则,不要将其用于未经授权的数据抓取或对目标服务造成过大压力。