Selenium是一款开源的自动化测试工具,核心优势在于能模拟真实用户操作浏览器(如点击、输入、滚动),并渲染动态加载的网页内容(解决Requests库无法爬取JS动态数据的问题)。
一、Selenium入门准备:环境搭建与核心原理
1. 核心原理
Selenium通过“浏览器驱动(Driver)”与浏览器通信:Python代码发送操作指令→Driver解析指令→浏览器执行操作并返回渲染后的页面数据,完美适配JS动态渲染的网页(如Ajax加载、Vue/React前端页面)。
2. 环境安装
(1)安装Selenium库
# 安装最新版Seleniumpipinstallselenium关键步骤:
- 查看浏览器版本(如Chrome:设置→关于Chrome,查看版本号);
- 下载对应版本的驱动(版本号需完全匹配,如Chrome 120.x对应ChromeDriver 120.x);
- 配置驱动路径:
- 方法1:将驱动文件放入Python安装目录(如Python39/Scripts),无需手动指定路径;
- 方法2:手动指定驱动路径(推荐,避免版本冲突)。
3. 验证环境
# 导入Selenium核心模块fromseleniumimportwebdriverfromselenium.webdriver.chrome.serviceimportService# 手动指定ChromeDriver路径driver_path="C:/chromedriver.exe"# Windows路径示例# 初始化浏览器对象driver=webdriver.Chrome(service=Service(driver_path))# 打开测试网页driver.get("https://www.baidu.com")# 打印网页标题(输出“百度一下,你就知道”则环境正常)print(driver.title)# 关闭浏览器driver.quit()二、Selenium基础操作:浏览器与页面控制
1. 浏览器核心操作
| 操作 | 代码示例 | 说明 |
|---|---|---|
| 打开网页 | driver.get("https://www.xxx.com") | 加载目标URL |
| 刷新页面 | driver.refresh() | 模拟浏览器刷新 |
| 前进/后退 | driver.forward()/driver.back() | 模拟浏览器前进/后退按钮 |
| 窗口最大化 | driver.maximize_window() | 避免元素因窗口过小无法定位 |
| 设置窗口大小 | driver.set_window_size(1920, 1080) | 自定义窗口分辨率 |
| 获取当前URL | driver.current_url | 查看当前页面URL(验证跳转是否成功) |
| 获取页面源码 | driver.page_source | 获取渲染后的完整HTML源码(含JS动态内容) |
2. 等待机制:解决元素加载延迟问题
网页动态加载时,直接定位元素会因“元素未加载完成”报错,Selenium提供3种等待方式:
(1)强制等待(不推荐)
importtime# 强制等待3秒(无论元素是否加载完成)time.sleep(3)(2)隐式等待(全局生效)
# 设置隐式等待:最长等待10秒,元素加载完成则立即执行driver.implicitly_wait(10)(3)显式等待(推荐,精准控制)
针对指定元素设置等待条件(如元素可点击、可见),超时则抛出异常:
fromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasECfromselenium.webdriver.common.byimportBy# 等待“百度搜索框”可见,最长等待10秒wait=WebDriverWait(driver,10)search_box=wait.until(EC.visibility_of_element_located((By.ID,"kw")))常用等待条件:
EC.visibility_of_element_located:元素可见;EC.element_to_be_clickable:元素可点击;EC.presence_of_element_located:元素存在于DOM中;EC.text_to_be_present_in_element:元素包含指定文本。
三、核心技能:元素定位(爬取/操作的关键)
元素定位是Selenium的核心,需根据网页结构选择最优定位方式,优先选择唯一标识(ID、Name),其次选择XPath/CSS选择器。
1. 8种定位方式(按优先级排序)
| 定位方式 | 代码示例 | 适用场景 |
|---|---|---|
| ID定位 | driver.find_element(By.ID, "kw") | 元素有唯一ID(如百度搜索框id=“kw”) |
| Name定位 | driver.find_element(By.NAME, "wd") | 元素有唯一Name属性 |
| Class定位 | driver.find_element(By.CLASS_NAME, "s_ipt") | 元素Class属性唯一 |
| Tag定位 | driver.find_element(By.TAG_NAME, "input") | 标签唯一(如页面唯一的input框) |
| Link文本定位 | driver.find_element(By.LINK_TEXT, "新闻") | 精准匹配超链接文本 |
| 部分Link文本 | driver.find_element(By.PARTIAL_LINK_TEXT, "新") | 模糊匹配超链接文本 |
| XPath定位 | driver.find_element(By.XPATH, '//*[@id="kw"]') | 无唯一属性时,万能定位方式 |
| CSS选择器 | driver.find_element(By.CSS_SELECTOR, "#kw") | 定位效率高于XPath,推荐使用 |
2. 实战:XPath/CSS选择器高级用法
(1)XPath定位(万能且灵活)
# 绝对路径(不推荐,页面结构变化易失效)driver.find_element(By.XPATH,"/html/body/div[1]/div[2]/input")# 相对路径+属性(推荐)driver.find_element(By.XPATH,'//input[@id="kw"]')# 包含文本的元素driver.find_element(By.XPATH,'//a[contains(text(), "百度首页")]')# 父节点定位子节点driver.find_element(By.XPATH,'//div[@class="s_form"]/input')(2)CSS选择器(效率更高)
# ID选择器driver.find_element(By.CSS_SELECTOR,"#kw")# Class选择器driver.find_element(By.CSS_SELECTOR,".s_ipt")# 属性选择器driver.find_element(By.CSS_SELECTOR,'input[name="wd"]')# 层级选择器driver.find_element(By.CSS_SELECTOR,"div.s_form > input")3. 批量定位元素
使用find_elements()(复数形式)获取多个元素,返回列表:
# 获取页面所有超链接links=driver.find_elements(By.TAG_NAME,"a")forlinkinlinks:print(link.get_attribute("href"))# 打印链接地址四、模拟用户操作:输入、点击、滚动等
1. 输入与清空
# 定位搜索框并输入内容search_box=driver.find_element(By.ID,"kw")search_box.send_keys("Selenium教程")# 输入文本search_box.clear()# 清空输入框search_box.send_keys("Python爬虫")# 重新输入2. 点击操作
# 点击搜索按钮search_btn=driver.find_element(By.ID,"su")search_btn.click()# 模拟回车键(替代点击按钮)search_box.send_keys(Keys.ENTER)3. 滚动页面
fromselenium.webdriver.common.keysimportKeys# 方式1:模拟键盘向下滚动(PageDown)driver.find_element(By.TAG_NAME,"body").send_keys(Keys.PAGE_DOWN)# 方式2:JS脚本滚动(精准控制)# 滚动到页面底部driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 滚动到指定元素位置target=driver.find_element(By.ID,"target_id")driver.execute_script("arguments[0].scrollIntoView();",target)4. 处理弹窗
(1)alert弹窗(系统弹窗)
# 等待弹窗出现alert=WebDriverWait(driver,10).until(EC.alert_is_present())# 获取弹窗文本print(alert.text)# 确认弹窗alert.accept()# 取消弹窗(仅confirm弹窗可用)# alert.dismiss()(2)iframe框架(嵌套页面)
需先切换到iframe,才能定位内部元素:
# 方式1:通过ID切换driver.switch_to.frame("iframe_id")# 方式2:通过元素定位切换iframe=driver.find_element(By.XPATH,'//iframe[@name="iframe_name"]')driver.switch_to.frame(iframe)# 操作iframe内元素driver.find_element(By.ID,"inner_btn").click()# 切回主页面driver.switch_to.default_content()5. 处理下拉框
fromselenium.webdriver.support.uiimportSelect# 定位下拉框select=Select(driver.find_element(By.ID,"select_id"))# 方式1:按索引选择(从0开始)select.select_by_index(1)# 方式2:按值选择(option的value属性)select.select_by_value("option_value")# 方式3:按文本选择select.select_by_visible_text("选项文本")# 获取所有选项options=select.optionsforoptioninoptions:print(option.text)五、进阶技巧:反爬规避与效率优化
1. 配置无界面模式(后台运行)
fromselenium.webdriver.chrome.optionsimportOptions# 创建Chrome配置对象chrome_options=Options()# 开启无界面模式chrome_options.add_argument("--headless=new")# 禁用GPU(避免无界面模式报错)chrome_options.add_argument("--disable-gpu")# 初始化浏览器(带配置)driver=webdriver.Chrome(service=Service(driver_path),options=chrome_options)2. 规避浏览器指纹检测
# 禁用自动化提示(去除“Chrome正受到自动测试软件控制”)chrome_options.add_experimental_option("excludeSwitches",["enable-automation"])chrome_options.add_experimental_option('useAutomationExtension',False)# 禁用Blink运行时功能chrome_options.add_argument("--disable-blink-features=AutomationControlled")# 设置用户代理(UA)chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")# 移除webdriver属性(关键反爬)driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")3. 多标签页/窗口操作
# 打开新标签页driver.execute_script("window.open('https://www.taobao.com')")# 获取所有标签页句柄windows=driver.window_handles# 切换到第二个标签页driver.switch_to.window(windows[1])# 关闭当前标签页driver.close()# 切回第一个标签页driver.switch_to.window(windows[0])4. 截图与日志
# 页面全屏截图driver.save_screenshot("page.png")# 元素截图element=driver.find_element(By.ID,"kw")element.screenshot("element.png")# 查看浏览器日志(排查错误)logs=driver.get_log("browser")forloginlogs:print(log)六、实战案例:爬取JS动态加载的商品数据
以某电商平台商品列表为例(JS动态加载),爬取商品名称、价格、销量:
fromseleniumimportwebdriverfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasECimporttime# 配置驱动路径driver_path="C:/chromedriver.exe"# 初始化浏览器driver=webdriver.Chrome(service=Service(driver_path))driver.maximize_window()driver.implicitly_wait(10)try:# 打开商品列表页driver.get("https://xxx.com/goods-list")# 滚动页面加载更多商品(模拟翻页)foriinrange(3):# 滚动3次# 滚动到页面底部driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")time.sleep(2)# 等待数据加载# 定位所有商品元素goods_list=WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CLASS_NAME,"goods-item")))# 解析商品信息forgoodsingoods_list:# 商品名称name=goods.find_element(By.CLASS_NAME,"goods-name").text# 商品价格price=goods.find_element(By.CLASS_NAME,"goods-price").text# 商品销量sales=goods.find_element(By.CLASS_NAME,"goods-sales").textprint(f"名称:{name},价格:{price},销量:{sales}")finally:# 关闭浏览器driver.quit()七、常见问题与避坑指南
- 驱动版本不匹配:报错“SessionNotCreatedException”,需下载与浏览器版本完全一致的驱动;
- 元素定位失败:
- 检查元素是否在iframe内(需先切换iframe);
- 检查元素是否动态加载(用显式等待替代强制等待);
- 避免使用绝对XPath(页面结构变化易失效);
- 反爬检测:被网站识别为爬虫时,添加UA、禁用自动化提示、随机滚动/点击间隔;
- 内存泄漏:务必用
driver.quit()关闭浏览器(而非driver.close()),避免进程残留; - 中文乱码:爬取的文本乱码时,添加编码设置:
driver.execute_script("document.charset='utf-8'")。