Selenium 从入门到精通:自动化测试与爬虫实战全攻略

#Selenium 是自动化领域中最经典、应用最广泛的工具之一。无论你是测试工程师,需要构建稳定的 UI 自动化测试,还是数据工程师,需要抓取复杂动态网页,Selenium 几乎都是绕不开的技能。本文将带你从零开始,循序渐进地掌握 Selenium 的核心用法,并深入高级技巧和实际项目,直至达到精通的水平。


一、入门基础:从环境搭建到第一个脚本

1. 环境准备

我们使用 Python 作为开发语言,因为它与 Selenium 结合得最紧密,社区资源也最丰富。

首先,安装 Selenium 库:

bash 复制代码
pip install selenium

Selenium 需要与浏览器驱动程序配合使用。以 Chrome 为例,你需要下载与本地 Chrome 版本匹配的 ChromeDriver(或者使用第三方驱动管理器自动处理)。简单的方法是安装 webdriver-manager

bash 复制代码
pip install webdriver-manager

这样就不用手动下载和配置驱动路径了。

2. 打开第一个网页

下面是最简单的示例,用 Chrome 打开百度首页:

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

# 自动管理驱动
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)

driver.get("https://www.baidu.com")
print(driver.title)  # 输出页面标题
driver.quit()

如果一切正常,浏览器会闪一下并自动关闭。至此,你已经跨入 Selenium 的大门。

3. 元素定位

Web 自动化的一切操作都建立在"找到元素"之上。Selenium 提供了多种定位策略:

  • find_element(By.ID, "id值")
  • find_element(By.NAME, "name值")
  • find_element(By.CLASS_NAME, "class值")
  • find_element(By.TAG_NAME, "标签名")
  • find_element(By.CSS_SELECTOR, "css表达式")
  • find_element(By.XPATH, "xpath表达式")

推荐优先使用 CSS 选择器,因为它简洁、可读性好且性能较高。当结构复杂时,可使用 XPath 的轴定位进行精准匹配。

示例:定位百度搜索框并输入关键词

python 复制代码
from selenium.webdriver.common.by import By

driver.get("https://www.baidu.com")
search_box = driver.find_element(By.ID, "kw")
search_box.send_keys("Selenium 教程")
search_btn = driver.find_element(By.ID, "su")
search_btn.click()

4. 基本操作

除了点击(click())和输入(send_keys()),常用操作还有:

  • 清空输入框:element.clear()
  • 获取文本:element.text
  • 获取属性:element.get_attribute("href")
  • 判断是否可见:element.is_displayed()

这些构成了自动化交互的基石。


二、进阶应用:让自动化更健壮

直接使用基础操作编写的脚本往往很脆弱:页面加载慢、元素未出现就会导致异常。下面我们学习让脚本变得稳定的关键技术。

1. 等待机制

隐式等待

设置一个全局的超时时间,Selenium 在查找元素时会轮询等待,直到元素出现或超时。

python 复制代码
driver.implicitly_wait(10)  # 最多等10秒

但隐式等待不够灵活,无法处理特定条件(如元素可点击)。

显式等待

使用 WebDriverWait 配合预期条件,这才是生产环境的首选。

python 复制代码
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
element.click()

常用预期条件:presence_of_element_locatedvisibility_of_element_locatedelement_to_be_clickabletext_to_be_present_in_element 等。显式等待让你的脚本在面对网络波动时依然稳定。

2. 处理特殊元素

下拉框(Select)

使用 Select 类操作 <select> 标签:

python 复制代码
from selenium.webdriver.support.ui import Select

select_element = driver.find_element(By.ID, "country")
select = Select(select_element)
select.select_by_value("cn")   # 按value选择
select.select_by_visible_text("中国")  # 按可见文本选择
弹窗(Alert)
python 复制代码
alert = driver.switch_to.alert
print(alert.text)
alert.accept()  # 点击确定
# alert.dismiss()  # 点击取消
多窗口切换

当点击链接打开新标签页时,需要切换窗口句柄:

python 复制代码
original_window = driver.current_window_handle
driver.find_element(By.LINK_TEXT, "打开新页面").click()
# 等待新窗口出现并切换
wait.until(EC.number_of_windows_to_be(2))
for handle in driver.window_handles:
    if handle != original_window:
        driver.switch_to.window(handle)
        break
# 操作新页面...
driver.close()  # 关闭当前标签
driver.switch_to.window(original_window)  # 切回原窗口

3. 执行 JavaScript

有些场景直接使用 WebDriver API 很难做到,例如修改元素的隐藏属性、滚动到页面底部等。这时可以执行 JavaScript:

python 复制代码
# 滚动到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 修改某个元素的样式使其可见
element = driver.find_element(By.ID, "hidden_div")
driver.execute_script("arguments[0].style.display='block';", element)

4. 截图与 Cookies

  • 截图:driver.save_screenshot("screenshot.png")
  • 保存 Cookies 用于登录状态复用:
python 复制代码
import pickle
cookies = driver.get_cookies()
with open("cookies.pkl", "wb") as f:
    pickle.dump(cookies, f)

# 后续加载
with open("cookies.pkl", "rb") as f:
    cookies = pickle.load(f)
    for cookie in cookies:
        driver.add_cookie(cookie)

三、高级技巧与实战:从可用到高效

掌握了上面的技能,你已经能完成大部分常规任务。但要达到精通,还需要深入性能优化、反爬对抗以及工程化设计。

1. 无头模式与性能优化

在服务器上运行或者追求速度时,可以启用无头模式(不显示界面):

python 复制代码
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")  # 新版无头模式
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("--window-size=1920,1080")

driver = webdriver.Chrome(options=options)

其他优化措施:

  • 禁用图片加载和CSS:通过 prefs 设置,可大幅减少流量和加载时间。
  • 使用 pageLoadStrategyeager,只等待 DOM 就绪,不等所有资源加载完。
  • 复用浏览器实例,避免频繁启动驱动。

2. 应对反爬虫机制

很多网站会检测自动化特征,Selenium 默认暴露的 navigator.webdriver 属性就是重要标志。可以通过启动参数和 CDP(Chrome DevTools Protocol)隐藏特征:

python 复制代码
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)

执行后再配合 CDP 命令进一步伪装:

python 复制代码
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined})
    """
})

如需更高隐蔽性,可以集成 selenium-stealth 库,一条命令即可应用常见伪装。

此外,搭配代理、随机等待时间、模拟人类操作曲线(如 ActionChainsmove_by_offset)等手段,可以让你的自动化脚本更难被识别。

3. 实战案例:抓取热榜数据

理论学习之后,我们通过一个完整的爬虫案例来融会贯通。目标是从热榜聚合网站抓取实时热点榜单,并保存为结构化数据。我们以 https://rebang.open2hub.com/ 为例,该网站汇集了多个平台的热搜,非常适合练手。

(请确保你的爬虫行为遵守网站的 robots.txt 协议及相关法律法规,合理控制频率。)

python 复制代码
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
from selenium.webdriver.chrome.options import Options
import time
import json

# 配置无头选项
options = Options()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 15)

try:
    driver.get("https://rebang.open2hub.com/")
    # 等待热榜容器加载完毕
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".hotlist")))

    # 根据不同平台提取热搜条目(此处简化为抓取所有标题)
    items = driver.find_elements(By.CSS_SELECTOR, ".hotlist .item")
    hot_data = []
    for item in items:
        title_elem = item.find_element(By.CSS_SELECTOR, ".title")
        hot_data.append({
            "title": title_elem.text,
            "link": title_elem.get_attribute("href"),
        })

    # 输出结果
    with open("hotlist.json", "w", encoding="utf-8") as f:
        json.dump(hot_data, f, ensure_ascii=False, indent=2)
    print(f"成功抓取 {len(hot_data)} 条热点")

finally:
    driver.quit()

这个案例示范了显式等待、元素提取、数据存储的完整流程。实际项目中,你还可以加入异常重试、日志记录和数据库写入等功能,使其更加稳健。

4. Page Object 设计模式

当测试或爬虫规模增大时,直接在脚本中写定位器会变得难以维护。Page Object 模式将页面抽象成类,每个页面有自己的定位器和行为。

python 复制代码
class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.username_input = (By.ID, "username")
        self.password_input = (By.ID, "password")
        self.login_btn = (By.ID, "login")

    def login(self, user, pwd):
        self.driver.find_element(*self.username_input).send_keys(user)
        self.driver.find_element(*self.password_input).send_keys(pwd)
        self.driver.find_element(*self.login_btn).click()
        return HomePage(self.driver)

class HomePage:
    def __init__(self, driver):
        self.driver = driver
        self.welcome_msg = (By.CSS_SELECTOR, ".welcome")

    def get_welcome_text(self):
        return self.driver.find_element(*self.welcome_msg).text

测试代码变得整洁且可读:

python 复制代码
driver.get("https://example.com/login")
login_page = LoginPage(driver)
home = login_page.login("user", "pass")
assert "欢迎" in home.get_welcome_text()

Page Object 是自动化测试工程化的基础,配合 pytest 等测试框架可以构建出稳定的回归测试套件。


四、精通之路:扩展生态与持续进阶

真正掌握 Selenium,不仅是熟练使用它的 API,更在于了解其在整个自动化生态中的位置,以及知道何时选择何种工具。

1. Selenium Grid 与分布式执行

当需要同时在不同浏览器、不同操作系统上运行测试时,Selenium Grid 提供了分布式解决方案。通过 Hub 和 Node 的模式,你可以将任务分发到多台机器并行执行。现代 Grid 还支持 Docker 部署,极大简化了环境一致性管理。

示例 Docker 命令启动一个 Hub 和 Chrome Node:

bash 复制代码
docker run -d -p 4444:4444 --name selenium-hub selenium/hub
docker run -d --link selenium-hub:hub selenium/node-chrome

然后在代码中连接远程 Hub:

python 复制代码
driver = webdriver.Remote(
    command_executor="http://localhost:4444/wd/hub",
    options=options
)

2. 与其他自动化工具的对比

  • Playwright:微软出品,自带浏览器驱动,API 更现代,支持自动等待和网络拦截,爬虫和测试表现都很好,但生态比 Selenium 年轻。
  • Puppeteer:仅支持 Chrome/Chromium,与 JavaScript 深度绑定,对前端开发者友好。
  • Cypress:定位为前端测试框架,实时重载、时光旅行调试,但不支持多标签切换和真正的多浏览器。

Selenium 的优势在于兼容性:它支持几乎所有浏览器(Chrome, Firefox, Edge, Safari),语言绑定丰富(Python, Java, C#, JS, Ruby)。如果你的项目需要跨浏览器覆盖或者与遗留系统集成,Selenium 仍然是稳妥的选择。

3. 持续学习建议

  • 阅读官方文档:最新的 API 变更和最佳实践都在那里。
  • 参与实际项目:无论是测试还是爬虫,实践中的坑才能让你真正成长。
  • 关注社区:Stack Overflow、博客、GitHub 上的相关仓库都充满有价值的信息。
  • 结合 CI/CD:将自动化脚本集成到 Jenkins、GitHub Actions 中,实现提交即测试,才算落地了完整的自动化流程。

结语

从第一个 driver.get() 到分布式 Grid,Selenium 的学习曲线并不陡峭,但真正用好它需要经验的积累和对 Web 技术的理解。无论你用它来做功能测试、回归测试,还是作为爬虫的渲染引擎,只要掌握了文中所述的核心技术、等待策略、反爬对抗和工程化设计,你就已经走上了从入门到精通的道路。希望这篇指南能成为你自动化之旅的可靠伙伴。

相关推荐
zhonghaoxincekj2 小时前
基于 168MHz MCU 的直流继电器全参数自动化测试方案解析
经验分享·功能测试·科技·学习·测试工具·创业创新·制造
北极星日淘2 小时前
Python爬虫断点续爬实战|基于Redis实现日淘商品增量抓取(解决重启全量重爬问题)
redis·爬虫·python
电商API_1800790524716 小时前
Python 实现闲鱼商品列表批量采集,接口异常重试机制搭建
大数据·开发语言·数据库·爬虫·python
带土116 小时前
5. 网络体系架构与WireShark简单使用
网络·测试工具·wireshark
kiss strong17 小时前
自制请求工具request-ui
测试工具
绘梨衣54719 小时前
采集基类设计遇到的描述符bug
爬虫·python·bug
蒲公英内测分发21 小时前
在灵感与输出之间挣扎:我与 Typeoff 的交集
测试工具·产品运营·项目管理·语音输入
川石课堂软件测试21 小时前
UI自动化测试|元素操作&浏览器操作实践
功能测试·测试工具·mysql·ui·docker·容器·单元测试
如烟花的信页1 天前
*花顺cookie逆向分析
javascript·爬虫·python·js逆向