Python Selenium自动化入门:从环境搭建到百度搜索实战
1. 项目概述:从手动点击到自动化操作的跨越
每次看到有人还在手动重复点击网页上的按钮、链接,或者为了测试一个功能而反复操作同一个流程时,我总想跟他们聊聊自动化。今天要聊的这个项目,就是用 Python 里的 Selenium 库,让程序代替你的手,去自动点击网页。我们以最熟悉的百度搜索页面作为实操案例,目标是写一个脚本,自动打开浏览器,在百度搜索框里输入关键词,然后点击“百度一下”按钮。听起来很简单,对吧?但这恰恰是自动化测试、数据采集(爬虫)乃至日常办公自动化的基石动作。无论你是想入门自动化测试的测试工程师,还是想绕过复杂接口直接抓取网页数据的开发者,或者是被繁琐的网页操作困扰的办公人员,掌握这个“点击”动作,就等于拿到了打开自动化世界大门的钥匙。
Selenium 之所以成为这个领域的首选,不是没有道理的。它不像一些简单的 HTTP 请求库(如 requests )只能获取静态页面,它能驱动一个真实的浏览器(比如 Chrome),执行所有你能手动完成的操作:点击、输入、滚动、下拉选择等等。这意味着它能处理由 JavaScript 动态生成的内容,这对于现代网页来说几乎是标配。而“谷歌驱动”(ChromeDriver)就是连接你的 Python 代码和谷歌 Chrome 浏览器的桥梁。整个流程可以概括为:你的 Python 脚本(使用 Selenium 库)发送指令 -> ChromeDriver 接收并翻译指令 -> 谷歌 Chrome 浏览器执行指令。这个项目,就是带你一步步搭建起这条指令通路,并完成一次完整的自动化点击操作。
2. 环境搭建与核心组件解析
2.1 Python 与 Selenium 库安装
工欲善其事,必先利其器。第一步是确保你有一个可用的 Python 环境。如果你还没安装 Python,可以去其官网下载最新稳定版。安装时务必勾选 “Add Python to PATH” 选项,这能让你在命令行中直接使用 python 和 pip 命令。安装完成后,打开命令行(Windows 上是 CMD 或 PowerShell,Mac/Linux 上是 Terminal),输入 python --version 来验证安装是否成功。
接下来安装 Selenium 库。在 Python 的世界里, pip 是包管理工具,安装第三方库几乎都是一条命令的事。在命令行中输入:
pip install selenium
这条命令会从 Python 的官方包索引中下载并安装最新版本的 Selenium。有时候网络环境可能导致下载缓慢或失败,你可以考虑使用国内的镜像源来加速,例如清华源:
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
安装完成后,可以在 Python 交互环境中输入 import selenium 来测试是否安装成功,不报错即表示成功。
注意:有些教程可能会让你安装一个叫
webdriver-manager的库来自动管理浏览器驱动。这对于新手快速上手非常友好,因为它能自动下载匹配的驱动版本。但对于理解整个工作原理而言,我建议第一次还是手动下载和配置驱动,这样你能更清楚地知道每个组件在哪里、起了什么作用。后续追求效率时再使用自动化管理工具。
2.2 谷歌浏览器驱动的下载与配置
这是新手最容易卡住的一步,也是核心所在。Selenium 本身不能直接控制浏览器,它需要通过一个名为 “WebDriver” 的中间件。对于 Chrome 浏览器,这个中间件就是 ChromeDriver 。关键点在于: ChromeDriver 的版本必须与你电脑上已安装的 Chrome 浏览器主版本号完全一致 。
首先,查看你 Chrome 浏览器的版本。打开 Chrome,点击右上角的三个点 -> 帮助 -> 关于 Google Chrome,就能看到版本号,比如 “版本 114.0.5735.199(正式版本)”。记住主版本号 “114”。
然后,去下载对应版本的 ChromeDriver。最权威的下载地址是 ChromeDriver 的官方存储站点。你需要下载与你的操作系统(Windows、macOS、Linux)匹配的文件。对于 Windows,通常下载 chromedriver_win32.zip 即可,即使你是 64 位系统。
下载后,你会得到一个 chromedriver.exe (Windows)或 chromedriver (Mac/Linux)的可执行文件。接下来需要配置环境变量,让 Python 脚本能找到它。有两种常用方法:
- 方法一:放置到 Python 脚本目录(推荐给新手) :将
chromedriver.exe文件直接复制到你的 Python 项目文件夹里。这样,在代码中指定驱动路径时,直接写./chromedriver.exe(相对路径)即可。这是最简单、最不容易出错的方式,尤其当你只有一个项目在使用时。 - 方法二:添加到系统 PATH 环境变量 :将
chromedriver.exe所在的目录路径(例如C:\WebDriver\bin)添加到系统的 PATH 环境变量中。这样,你可以在系统的任何位置通过命令行启动它,在代码中也无需指定路径,Selenium 会自动在 PATH 中查找。这种方法更通用,但配置稍复杂。
实操心得:版本不匹配是 90% 的失败原因。如果启动时报错提示“无法启动 Chrome”、“This version of ChromeDriver only supports Chrome version XX”等,请再次核对版本。另一个常见坑点是,Chrome 浏览器会自动更新,但你的 ChromeDriver 不会。如果某天脚本突然不能用了,首先检查 Chrome 是否自动升级了,然后去下载对应新版本的驱动替换掉旧的。
2.3 编写你的第一个自动化脚本:打开浏览器
环境准备好后,我们就可以开始写代码了。创建一个新的 Python 文件,比如 baidu_auto_click.py 。首先,导入 Selenium 中用于操作 Chrome 浏览器的部分:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
webdriver:这是核心模块,用于启动和控制浏览器。By:这个类提供了定位网页元素的各种方法(如通过 ID、类名、标签名等),是后续“找到”按钮和输入框的关键。Keys:模拟键盘按键,比如回车键。time:用于在操作之间添加短暂的等待,让页面有足够时间加载。这是一个简单的等待方法,后续我们会介绍更优的等待策略。
接下来,初始化浏览器驱动并打开一个网页:
# 指定 ChromeDriver 的路径,如果已加入 PATH 则无需此参数
driver = webdriver.Chrome(executable_path='./chromedriver.exe') # 假设驱动放在同级目录
# 打开百度首页
driver.get("https://www.baidu.com")
# 等待3秒,观察浏览器是否成功打开
time.sleep(3)
# 关闭浏览器
driver.quit()
运行这段代码,你应该会看到一个新的 Chrome 浏览器窗口被自动打开,并跳转到百度首页,停留3秒后关闭。恭喜你,你已经成功用代码驱动了浏览器!这里的 driver.get() 方法就相当于你在地址栏输入网址并回车。 driver.quit() 会关闭整个浏览器窗口及其相关的驱动进程,而 driver.close() 只会关闭当前标签页。在脚本结束时,通常使用 quit() 来彻底清理。
3. 核心操作:定位元素与模拟点击
3.1 理解网页的“身份证”:HTML 元素与定位器
要让程序去点击“百度一下”按钮,首先得告诉它按钮在哪里。网页是由 HTML 代码构成的,每个按钮、输入框、链接都是一个 HTML 元素,它们通常有各种“属性”作为身份证。我们需要使用 By 类提供的定位器来找到它们。
最常见的定位方式有:
By.ID:通过元素的id属性定位。id在理想情况下应该是页面内唯一的,是最快速、最可靠的定位方式。By.NAME:通过元素的name属性定位。By.CLASS_NAME:通过元素的class属性定位。注意,一个元素可能有多个 class,这里匹配的是其中一个。By.TAG_NAME:通过元素的标签名定位,如input,button,a。通常一个页面有很多同标签元素,不够精确。By.XPATH:一种非常强大和灵活的定位语言,可以遍历 XML/HTML 文档的节点。当元素没有好的id或name时,XPATH 是救星。By.CSS_SELECTOR:使用 CSS 选择器语法来定位元素,同样非常强大和灵活,是很多前端开发者和自动化工程师的首选。
如何查看元素的这些属性?在浏览器中打开百度首页,在搜索输入框上点击鼠标右键,选择“检查”(Inspect)。开发者工具会打开,并高亮显示对应的 HTML 代码。你会发现输入框的代码大概长这样:
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
这里, id="kw" , name="wd" , class="s_ipt" 。同样,检查“百度一下”按钮,可能会看到 id="su" 或者 class="bg s_btn" 等属性。
3.2 实现搜索自动化:输入与点击
现在,我们修改脚本,实现完整的搜索流程。在打开百度首页后,添加以下代码:
# 定位百度搜索框,并输入关键词“Selenium”
search_box = driver.find_element(By.ID, 'kw')
search_box.send_keys('Selenium')
# 定位“百度一下”按钮,并点击
search_button = driver.find_element(By.ID, 'su')
search_button.click()
# 等待几秒,查看搜索结果
time.sleep(5)
driver.find_element(By.ID, 'kw'):这行代码让 Selenium 在页面中查找id属性为kw的元素,也就是搜索框,并将找到的元素对象赋值给变量search_box。search_box.send_keys('Selenium'):在找到的搜索框元素上模拟键盘输入,输入字符串 “Selenium”。driver.find_element(By.ID, 'su'):查找id为su的按钮元素。search_button.click():在找到的按钮元素上模拟鼠标点击操作。
运行脚本,你会看到浏览器自动在百度搜索框中输入了“Selenium”并点击搜索,跳转到结果页。这就是一次完整的自动化交互。
注意事项:
find_element和find_elements的区别。find_element返回找到的第一个匹配元素,如果没找到会抛出NoSuchElementException异常。find_elements(注意复数)返回一个包含所有匹配元素的列表,如果没找到则返回空列表。当你需要操作一组相似元素(如搜索结果列表)时,使用后者。
3.3 更健壮的定位策略与等待机制
上面的例子使用了 time.sleep(3) ,这是一种“强制等待”。它简单粗暴,但效率低下。如果网络或电脑慢,3秒可能不够页面加载完元素;如果很快,又会白白浪费时间。在实际项目中,我们使用 Selenium 提供的“智能等待”。
1. 隐式等待 (Implicit Wait): 在创建 driver 后设置一次,对整个 driver 的生命周期都有效。它告诉 WebDriver:在查找元素时,如果元素没有立即出现,就等待一段设定的时间,期间会持续尝试查找,直到找到或超时。
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 单位是秒
设置后,后续所有的 find_element 操作都会最多等待10秒。
2. 显式等待 (Explicit Wait): 更灵活、更推荐的方式。它为某个特定的操作和元素设定等待条件,比如等待元素可见、可点击、存在等。这需要用到 WebDriverWait 和 expected_conditions 。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 等待搜索框出现并且是可交互的状态(可见、可输入)
wait = WebDriverWait(driver, 10) # 最长等10秒
search_box = wait.until(EC.element_to_be_clickable((By.ID, 'kw')))
search_box.send_keys('Selenium')
# 等待搜索按钮可点击
search_button = wait.until(EC.element_to_be_clickable((By.ID, 'su')))
search_button.click()
WebDriverWait(driver, timeout) 创建一个等待对象。 until(condition) 方法会一直等待,直到传入的条件函数返回 True(找到了元素)或超时。 expected_conditions 模块提供了很多预设条件,如 presence_of_element_located (元素存在于DOM)、 visibility_of_element_located (元素可见)、 element_to_be_clickable (元素可点击)等。
为什么推荐显式等待? 因为它更精确。隐式等待是对所有 find 操作生效的全局设置,有时可能会在不需要等待的地方产生不必要的延迟。显式等待则针对具体场景,代码意图更清晰,且能等待更复杂的条件(如元素包含特定文本)。
4. 实战扩展与常见问题排查
4.1 处理更复杂的交互与页面结构
掌握了基本点击和输入后,你可以尝试更复杂的操作,这些操作能应对绝大多数网页自动化场景。
处理下拉框 (Select):
from selenium.webdriver.support.ui import Select
# 假设有一个id为‘city’的下拉框
dropdown = Select(driver.find_element(By.ID, 'city'))
dropdown.select_by_visible_text('北京') # 通过文本选择
# 或者 dropdown.select_by_value('beijing') # 通过value属性选择
# 或者 dropdown.select_by_index(1) # 通过索引选择(从0开始)
执行 JavaScript: 有些操作 Selenium 没有直接提供 API,或者用 JavaScript 更简单,可以直接执行 JS 代码。
# 将页面滚动到底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 点击一个被其他元素遮挡的按钮(如果普通click无效)
button = driver.find_element(By.ID, 'hidden-btn')
driver.execute_script("arguments[0].click();", button)
切换窗口和iframe:
- 窗口切换 :点击一个链接后可能打开新标签页,需要切换句柄。
# 获取当前所有窗口句柄
main_window = driver.current_window_handle
all_windows = driver.window_handles
# 点击某个会打开新窗口的链接
driver.find_element(By.LINK_TEXT, '新窗口').click()
# 切换到新窗口
for window in driver.window_handles:
if window != main_window:
driver.switch_to.window(window)
break
# 在新窗口操作...
# 操作完后可以切回主窗口
driver.switch_to.window(main_window)
- iframe切换 :如果元素位于一个
<iframe>框架内,必须先切换到该框架才能操作其中的元素。
# 通过id或name切换
driver.switch_to.frame('iframe_id_or_name')
# 或者通过元素对象切换
iframe_element = driver.find_element(By.TAG_NAME, 'iframe')
driver.switch_to.frame(iframe_element)
# 操作iframe内的元素...
# 操作完成后切回主文档
driver.switch_to.default_content()
4.2 常见问题与排查技巧实录
自动化脚本在运行时总会遇到各种意想不到的问题,这里记录几个最常见的问题和排查思路。
问题1: NoSuchElementException - 找不到元素 这是最最常见的错误。
- 可能原因1:页面未加载完 。解决方案:增加等待时间,使用显式等待(
WebDriverWait+EC)替代time.sleep。 - 可能原因2:元素在 iframe 或 shadow DOM 内 。解决方案:先切换到正确的 iframe 或 shadow root 内再查找。
- 可能原因3:元素是动态生成的,ID/Class 不固定 。解决方案:使用更稳定的定位策略,如通过部分文本(
By.XPATH的contains(text(), ‘部分文本’))、通过父元素的稳定属性结合子元素关系定位。 - 排查技巧 :在抛出异常的代码行之前,手动添加
time.sleep(10),然后运行脚本。当脚本暂停时,立即去浏览器里手动检查元素(右键 -> 检查),确认你使用的定位器(如id=‘kw’)在当前页面结构中是否依然存在且唯一。浏览器的开发者工具中,按Ctrl+F可以在Elements面板里直接输入 XPath 或 CSS Selector 进行测试匹配。
问题2: ElementNotInteractableException - 元素不可交互 元素找到了,但无法点击或输入。
- 可能原因1:元素被遮挡 。例如被一个弹窗、浮动层盖住了。解决方案:关闭遮挡物,或者用
driver.execute_script(“arguments[0].click();”, element)通过 JS 直接点击。 - 可能原因2:元素不可见或未启用 。解决方案:等待元素变为可见/可点击状态(使用
EC.visibility_of_element_located或EC.element_to_be_clickable)。 - 可能原因3:需要滚动到元素位置 。有些元素需要出现在视口中才能交互。解决方案:先滚动到元素位置
driver.execute_script(“arguments[0].scrollIntoView(true);”, element)。
问题3:脚本在无头模式下运行正常,但有界面时失败 无头模式 ( headless ) 是指浏览器在后台运行,不显示图形界面。有时脚本在无头模式下正常,但打开界面就失败。
- 可能原因:界面加载了更多资源或动画,导致元素状态变化时机不同 。解决方案:在关键操作前增加更长的等待或更严格的等待条件(如等待元素
staleness状态结束)。另外,检查是否有基于视口大小或鼠标位置的动态内容。
问题4:浏览器被检测为自动化工具 一些网站(如某些登录页面)会检测浏览器是否被 Selenium 等自动化工具驱动,并拒绝服务。
- 应对策略 :
- 使用
undetected-chromedriver等第三方库 :它专门用于规避检测。 - 添加实验性选项 :在启动 Chrome 时添加一些参数来隐藏自动化特征。
from selenium.webdriver.chrome.options import Options options = Options() options.add_argument(“--disable-blink-features=AutomationControlled”) options.add_experimental_option(“excludeSwitches”, [“enable-automation”]) options.add_experimental_option(‘useAutomationExtension’, False) driver = webdriver.Chrome(options=options) # 同时执行一个脚本,覆盖 navigator.webdriver 属性 driver.execute_script(“Object.defineProperty(navigator, ‘webdriver’, {get: () => undefined})”)- 模拟真人操作 :添加随机延迟、模拟鼠标移动轨迹等。但这会大大增加脚本复杂度和运行时间。
- 使用
4.3 代码优化与项目结构建议
当你的自动化脚本越来越复杂时,良好的代码组织至关重要。
1. 使用 Page Object Model (POM) 设计模式: 这是自动化测试领域的经典模式。其核心思想是将每个页面封装成一个类,页面的元素定位器和操作这个页面的方法都定义在这个类里。这样,测试脚本(业务逻辑)就和具体的页面元素定位细节分离开了。
# pages/baidu_page.py
class BaiduPage:
def __init__(self, driver):
self.driver = driver
self.search_input = (By.ID, ‘kw’)
self.search_button = (By.ID, ‘su’)
def open(self):
self.driver.get(“https://www.baidu.com”)
def search_for(self, keyword):
wait = WebDriverWait(self.driver, 10)
input_elem = wait.until(EC.presence_of_element_located(self.search_input))
input_elem.clear()
input_elem.send_keys(keyword)
self.driver.find_element(*self.search_button).click()
# main.py
from pages.baidu_page import BaiduPage
driver = webdriver.Chrome()
page = BaiduPage(driver)
page.open()
page.search_for(“自动化测试”)
这样做的好处是:元素定位符只在一处维护,如果页面改了,只需要修改对应的 Page 类;测试脚本变得非常清晰,读起来就像业务描述。
2. 配置文件管理: 将浏览器类型、驱动路径、基础URL、超时时间等配置信息提取到配置文件(如 config.ini 或 config.py )中,方便不同环境切换。
# config.py
CHROME_DRIVER_PATH = ‘./drivers/chromedriver.exe’
IMPLICIT_WAIT_TIME = 10
BASE_URL = ‘https://www.baidu.com’
# 在代码中使用
from config import CHROME_DRIVER_PATH
driver = webdriver.Chrome(executable_path=CHROME_DRIVER_PATH)
3. 日志记录: 使用 Python 的 logging 模块记录脚本运行的关键步骤和错误信息,而不是简单用 print 。这对于后期调试和问题追溯非常有帮助。
import logging
logging.basicConfig(level=logging.INFO,
format=‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’)
logger = logging.getLogger(__name__)
logger.info(“开始打开浏览器...”)
driver.get(BASE_URL)
logger.info(“百度首页加载完成。”)
4. 异常处理与截图: 在关键操作步骤周围使用 try…except 块捕获异常,并在出错时自动截图,能让你快速知道失败时页面是什么样子。
try:
search_box = driver.find_element(By.ID, ‘kw’)
search_box.send_keys(‘test’)
except Exception as e:
logger.error(f“搜索操作失败: {e}”)
# 保存截图,文件名包含时间戳
timestamp = time.strftime(“%Y%m%d_%H%M%S”)
driver.save_screenshot(f“error_screenshot_{timestamp}.png”)
raise # 可以选择重新抛出异常,或者进行其他处理
掌握了这些基础操作、问题排查方法和优化技巧,你就已经跨过了 Selenium 自动化操作的门槛。从自动点击百度搜索开始,你可以将这套方法应用到需要登录、填写表单、爬取数据、监控网页变化等无数场景中。记住,自动化不是为了炫技,而是为了将人从重复、枯燥的劳动中解放出来。开始动手,把你的第一个脚本跑起来,遇到问题就按上面的思路去排查,每一步解决问题的过程,都是你宝贵的经验积累。
更多推荐


所有评论(0)