浏览器自动化,为何90%的Python开发者最后都选了它


在这里插入图片描述

浏览器自动化,为何90%的Python开发者最后都选了它


第一部分:背景——为什么我要让浏览器自己动起来

在日常测试、数据采集、自动化报表等场景中,你是否需要:

  • 每天登录后台点 30 次按钮下载 Excel?
  • 在 100 个商品页间来回跳转截图?
  • 模拟真实用户操作验证前端交互?

纯 HTTP 请求库(requestsaiohttp)无法执行 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,让你的浏览器自己动起来吧!
如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘎啦AGI实验室

你的鼓励是我创作最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值