什么是 Selenium
Selenium 是一个用于 Web 应用程序自动化测试的开源工具。它可以模拟用户在浏览器中的各种操作,如点击、输入、滚动等,广泛应用于自动化测试、爬虫、RPA(机器人流程自动化)等场景。
环境准备
1. 安装 Selenium
bash
pip install selenium
2. 下载浏览器驱动
Selenium 需要对应浏览器的驱动程序:
- Chrome: ChromeDriver
- Firefox: GeckoDriver
- Edge: EdgeDriver
确保驱动版本与浏览器版本匹配。
基本用法
1. 启动浏览器
python
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# 配置选项
chrome_options = Options()
chrome_options.add_argument('--start-maximized') # 最大化窗口
# 启动浏览器
driver = webdriver.Chrome(options=chrome_options)
# 或者指定驱动路径
service = Service('path/to/chromedriver.exe')
driver = webdriver.Chrome(service=service, options=chrome_options)
2. 打开网页
python
driver.get('https://www.example.com')
3. 关闭浏览器
python
driver.quit() # 关闭所有窗口并退出驱动
driver.close() # 仅关闭当前窗口
元素定位
Selenium 提供多种元素定位方式:
python
from selenium.webdriver.common.by import By
# 通过 ID 定位
element = driver.find_element(By.ID, "username")
# 通过 Name 定位
element = driver.find_element(By.NAME, "password")
# 通过 Class Name 定位
element = driver.find_element(By.CLASS_NAME, "submit-btn")
# 通过 Tag Name 定位
element = driver.find_element(By.TAG_NAME, "input")
# 通过 CSS 选择器定位
element = driver.find_element(By.CSS_SELECTOR, "#login-form .btn")
# 通过 XPath 定位
element = driver.find_element(By.XPATH, "//button[@type='submit']")
# 通过链接文本定位
element = driver.find_element(By.LINK_TEXT, "点击这里")
# 通过部分链接文本定位
element = driver.find_element(By.PARTIAL_LINK_TEXT, "点击")
# 查找多个元素
elements = driver.find_elements(By.CLASS_NAME, "item")
元素操作
1. 输入文本
python
input_element = driver.find_element(By.ID, "username")
input_element.clear() # 清空输入框
input_element.send_keys("admin") # 输入文本
2. 点击元素
python
button = driver.find_element(By.ID, "submit")
button.click()
3. 获取元素属性和文本
python
element = driver.find_element(By.ID, "title")
# 获取文本内容
text = element.text
# 获取属性值
href = element.get_attribute("href")
class_name = element.get_attribute("class")
# 判断元素状态
element.is_displayed() # 是否可见
element.is_enabled() # 是否可用
element.is_selected() # 是否选中(复选框/单选框)
4. 使用 JavaScript 操作
python
# 执行 JavaScript
driver.execute_script("alert('Hello!')")
# 滚动页面
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
# 点击元素(解决某些元素无法直接点击的问题)
element = driver.find_element(By.ID, "btn")
driver.execute_script("arguments[0].click();", element)
# 修改元素属性
driver.execute_script("arguments[0].value = 'new value';", element)
等待机制
1. 显式等待(推荐)
python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10) # 最长等待10秒
# 等待元素出现
element = wait.until(EC.presence_of_element_located((By.ID, "content")))
# 等待元素可见
element = wait.until(EC.visibility_of_element_located((By.ID, "content")))
# 等待元素可点击
element = wait.until(EC.element_to_be_clickable((By.ID, "button")))
# 等待元素消失
wait.until(EC.invisibility_of_element_located((By.ID, "loading")))
# 等待文本出现
wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "完成"))
2. 隐式等待
python
driver.implicitly_wait(10) # 全局设置,等待元素最长10秒
3. 强制等待(不推荐)
python
import time
time.sleep(3) # 强制等待3秒
处理特殊场景
1. 处理 iframe
python
# 切换到 iframe
iframe = driver.find_element(By.ID, "myframe")
driver.switch_to.frame(iframe)
# 也可以通过索引切换
driver.switch_to.frame(0)
# 切回主页面
driver.switch_to.default_content()
# 切换到父级 frame
driver.switch_to.parent_frame()
2. 处理弹窗(Alert)
python
# 切换到弹窗
alert = driver.switch_to.alert
# 获取弹窗文本
text = alert.text
# 接受弹窗(点击确定)
alert.accept()
# 取消弹窗(点击取消)
alert.dismiss()
# 输入文本(prompt 弹窗)
alert.send_keys("input text")
3. 处理多窗口
python
# 获取当前窗口句柄
main_window = driver.current_window_handle
# 获取所有窗口句柄
all_windows = driver.window_handles
# 切换到新窗口
for window in all_windows:
if window != main_window:
driver.switch_to.window(window)
break
# 切回主窗口
driver.switch_to.window(main_window)
4. 处理下拉框
python
from selenium.webdriver.support.ui import Select
select_element = driver.find_element(By.ID, "dropdown")
select = Select(select_element)
# 通过索引选择
select.select_by_index(1)
# 通过 value 属性选择
select.select_by_value("option1")
# 通过可见文本选择
select.select_by_visible_text("选项一")
# 获取所有选项
options = select.options
# 获取当前选中项
selected = select.first_selected_option
截图功能
python
# 整个页面截图
driver.save_screenshot("screenshot.png")
# 获取截图二进制数据
png_data = driver.get_screenshot_as_png()
# 元素截图
element = driver.find_element(By.ID, "content")
element.screenshot("element.png")
浏览器配置
1. 无头模式(不显示浏览器窗口)
python
chrome_options = Options()
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(options=chrome_options)
2. 禁用图片加载(加速)
python
chrome_options = Options()
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_options.add_experimental_option("prefs", prefs)
3. 设置代理
python
chrome_options = Options()
chrome_options.add_argument('--proxy-server=http://127.0.0.1:8080')
4. 忽略 SSL 证书错误
python
chrome_options = Options()
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--ignore-ssl-errors')
5. 禁用自动化检测
python
chrome_options = Options()
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_experimental_option('useAutomationExtension', False)
键盘操作
python
from selenium.webdriver.common.keys import Keys
element = driver.find_element(By.ID, "input")
# 模拟键盘按键
element.send_keys(Keys.ENTER) # 回车
element.send_keys(Keys.TAB) # Tab
element.send_keys(Keys.ESCAPE) # ESC
element.send_keys(Keys.BACKSPACE) # 退格
# 组合键
element.send_keys(Keys.CONTROL, 'a') # Ctrl+A 全选
element.send_keys(Keys.CONTROL, 'c') # Ctrl+C 复制
element.send_keys(Keys.CONTROL, 'v') # Ctrl+V 粘贴
鼠标操作
python
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
element = driver.find_element(By.ID, "menu")
# 鼠标悬停
actions.move_to_element(element).perform()
# 双击
actions.double_click(element).perform()
# 右键点击
actions.context_click(element).perform()
# 拖拽
source = driver.find_element(By.ID, "source")
target = driver.find_element(By.ID, "target")
actions.drag_and_drop(source, target).perform()
# 链式操作
actions.move_to_element(menu).click().send_keys("text").perform()
完整示例
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
def main():
# 配置浏览器
options = Options()
options.add_argument('--start-maximized')
# 启动浏览器
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
try:
# 打开网页
driver.get('https://www.example.com')
# 等待并输入用户名
username = wait.until(EC.presence_of_element_located((By.ID, "username")))
username.send_keys("admin")
# 输入密码
password = driver.find_element(By.ID, "password")
password.send_keys("123456")
# 点击登录按钮
login_btn = wait.until(EC.element_to_be_clickable((By.ID, "login")))
login_btn.click()
# 等待登录成功
wait.until(EC.presence_of_element_located((By.ID, "dashboard")))
print("登录成功!")
# 截图
driver.save_screenshot("success.png")
except Exception as e:
print(f"操作失败: {e}")
driver.save_screenshot("error.png")
finally:
driver.quit()
if __name__ == "__main__":
main()
常见问题
1. 元素找不到
- 检查元素是否在 iframe 中
- 使用显式等待确保元素加载完成
- 检查元素定位器是否正确
2. 元素无法点击
- 元素可能被其他元素遮挡
- 尝试使用 JavaScript 点击
- 滚动页面使元素可见
3. 页面加载慢
- 使用显式等待而非强制等待
- 考虑禁用图片加载
- 使用无头模式
总结
Selenium 是一个功能强大的 Web 自动化工具,掌握元素定位、等待机制、特殊场景处理等核心概念后,就能应对大多数自动化需求。建议在实践中多尝试不同的定位方式和等待策略,找到最适合的解决方案。