☰
机器学习之Selenium(Machina Learning about Selenium)
2026/9/27 5:06:21 网站建设 项目流程

四、爬虫自动化——Selenium

1、Selenium基础知识与元素定位

1.1 Selenium介绍

在之前的文章中我们能够深刻学习到使用 request 库进行网页爬取。requests 只能获取服务器返回的 HTML 源码,但是现在网页越来越复杂,很多东西都是通过 JavaScript 进行动态加载。

  • Ajax异步加载:微博、知乎的内容都是滚动自动加载更多
  • SPA单页应用:整个应用在一个页面,切换页面不刷新浏览器
  • 动态渲染:搜索结果、评论列表等需要JS执行后才能够显示

这时候,requests就无法获取到这些动态加载的内容了。因此需要一个能够执行JS的工具库——Selenium。

1.2 Selenium工作原理

Selenium整体架构图示:

工作流程分解:

  1. Python脚本通过WebDriver协议与浏览器驱动通信
  2. 浏览器驱动解析命令并且控制浏览器
  3. 浏览器执行实际操作
  4. 结果通过驱动返回给Python脚本

1.3 安装与配置Selenium

安装Python库:

💡pip install selenium

下载浏览器驱动:

Selenium版本使用的是W3C WebDriver协议,每个浏览器都需要对应的驱动:

浏览器驱动下载
Chrome
https://chromedriver.chromium.org/downloads
Firefox
https://github.com/mozilla/geckodriver/releases
Edge
https://msedgedriver.azureedge.net/

放置驱动:

  1. 将驱动放到系统PATH环境变量所在目录
  2. 在代码中指定驱动路径
1.4 8中元素点位方式
from selenium import webdriver from selenium.webdriver.common.by import By # 定位方式在这个类里 # 方式1:通过ID定位(最推荐,有唯一性) driver.find_element(By.ID, 'kw') # 查找 id="kw" 的元素 # 方式2:通过NAME属性定位 driver.find_element(By.NAME, 'wd') # 查找 name="wd" 的元素 # 方式3:通过XPATH定位(最强大,可写任意条件) driver.find_element(By.XPATH, '//input[@id="kw"]') # 相对路径 driver.find_element(By.XPATH, '//div[@class="wrapper"]//input') # 支持层级 # 方式4:通过CSS选择器定位(也很强大) driver.find_element(By.CSS_SELECTOR, '#kw') # ID选择器 driver.find_element(By.CSS_SELECTOR, '.s_ipt') # 类选择器 driver.find_element(By.CSS_SELECTOR, 'input[name="wd"]') # 属性选择器 # 方式5:通过CLASS_NAME定位(注意:class有多个时只能选一个) driver.find_element(By.CLASS_NAME, 's_ipt') # 查找 class="s_ipt" 的元素 # 方式6:通过标签名定位 driver.find_element(By.TAG_NAME, 'input') # 查找第一个 <input> 标签 # 方式7:通过完整链接文字定位 driver.find_element(By.LINK_TEXT, '新闻') # 查找链接文字完全匹配"新闻"的<a> # 方式8:通过部分链接文字定位 driver.find_element(By.PARTIAL_LINK_TEXT, '新') # 查找链接文字包含"新"的<a>

定位方式选择建议:

  • 有ID使用ID
  • 复杂条件使用XPATH或CSS
  • 链接文字使用LINK_TEXT或PARTIALL_LINK_TEXT
  • 多个同类元素,使用find_element(加s)获取列表

1.5 实战示例

""" Selenium基本使用流程: 1. 导入库 2. 配置选项(可选) 3. 创建driver对象 4. 打开网页 5. 定位元素并操作 6. 获取结果 7. 关闭浏览器 """ from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys # 键盘按键 from selenium.webdriver.chrome.options import Options # Chrome配置 from selenium.webdriver.chrome.service import Service # ==================== 配置无头模式 ==================== # 无头模式:不显示浏览器窗口,后台运行 options = Options() #options.add_argument('--headless') # 开启无头模式 options.add_argument('--disable-gpu') # 禁用GPU硬件加速 options.add_argument('--window-size=1920,1080') # 设置窗口大小 # ==================== 创建driver并操作 ==================== # 创建Chrome浏览器实例 # 指定 chromedriver 路径 service = Service('chromedriver.exe') driver = webdriver.Chrome(service=service, options=options) # 打开百度首页 driver.get('https://www.baidu.com') # 定位搜索框(通过ID) search_box = driver.find_element(By.ID, 'kw') # 在搜索框输入文字 search_box.send_keys('Python') # 按下回车键(Keys.RETURN = Enter键) search_box.send_keys(Keys.RETURN) # 等待页面加载后,获取标题 print(f'页面标题:{driver.title}') # 截图保存 driver.save_screenshot('result.png') # ==================== 关闭浏览器 ==================== driver.quit() # 正常关闭 # driver.close() # 只关闭当前窗口,不释放资源

💡使用异常处理机制:

  • 1.NoSuchElementException:找不到元素,可能是还没加载完成,需要加等待
  • 2.ElementNotInteractableException:元素不可交互,可能在iframe里或被遮挡
  • 3.StaleElementReferenceException:元素过期,页面已刷新需要重新定位
  • 4.WebDriverException:驱动问题,检查驱动版本是否匹配

2、Selenium等待与交互

2.1 等待用途

在使用Selenium时,常见的问题是“元素找不到”,主要是因为:

  • 网络延迟导致页面加载慢
  • 网页使用Ajax异步加载,数据不是一次性返回
  • JavaScript执行需要时间

例如当加载页面时:

  1. 收到HTML文档(requests获取)
  2. 解析HTML,发现需要加载JS/CSS/图片
  3. 执行JavaScript,需要请求更多的数据
  4. DOM更新,页面内容完成最终渲染

如果在第一步完成后就立刻查找元素,那些通过JS动态生成的内容肯定找不到,因此需要等待。

2.2 等待方式

等待方式语法优点缺点场景
强制等待time.sleep()简单浪费时间调试时临时调用
隐式等待driver.implicitly_wait()设置一次全局生效只对于查找元素生效配合显示等待使用
显示等待WebDriverWait()条件满足继续代码复杂推荐使用
import time 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 service = Service('chromedriver.exe') driver = webdriver.Chrome(service=service) # ==================== 方式1:强制等待 ==================== # 不管元素是否加载完成,都等够指定时间 time.sleep(3) # 必须等3秒,即使1秒就加载完了 # ==================== 方式2:隐式等待 ==================== # 设置全局等待时间,在查找元素时会轮询直到找到或超时 driver.implicitly_wait(10) # 10秒内一直尝试找元素 driver.get('https://example.com') element = driver.find_element(By.ID, 'content') # 会等待最多10秒 # ==================== 方式3:显式等待(推荐) ==================== # 更智能,只等到条件满足为止 wait = WebDriverWait(driver, timeout=10) # 最多等10秒 # 等待元素出现(存在DOM中) element = wait.until( EC.presence_of_element_located((By.ID, 'content')) ) # 等待元素可点击 button = wait.until( EC.element_to_be_clickable((By.ID, 'submit')) ) # 等待元素可见 visible_element = wait.until( EC.visibility_of_element_located((By.CLASS_NAME, 'result')) )

2.3 常用等待条件

expected_conditions 模块提供了预支等待条件:

from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 判断元素存在(DOM中存在即可,不一定可见) EC.presence_of_element_located((By.ID, 'element_id')) # 判断元素可见(肉眼可见) EC.visibility_of_element_located((By.ID, 'element_id')) # 判断元素可点击(可见且启用) EC.element_to_be_clickable((By.ID, 'element_id')) # 判断元素被选中(checkbox/radio) EC.element_to_be_selected((By.ID, 'element_id')) # 判断文本出现在元素中 EC.text_to_be_present_in_element((By.ID, 'element_id'), '期望的文本') # 判断页面标题包含某文字 EC.title_contains('期望的标题') # 判断元素可交互(可见且启用) EC.element_to_be_clickable((By.XPATH, '//button[@type="submit"]')) # 等待多个元素中的任意一个出现 EC.presence_of_all_elements_located((By.TAG_NAME, 'a'))

示例:

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.service import Service service = Service('chromedriver.exe') driver = webdriver.Chrome(service=service) driver.get('https://www.baidu.com') # 创建等待对象,设置超时10秒,轮询间隔0.5秒 wait = WebDriverWait(driver, 10, poll_frequency=0.5) # 等待搜索框出现并可交互 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() # 等待搜索结果标题包含关键词 wait.until(EC.title_contains('Selenium')) print(f'搜索完成,标题:{driver.title}')

2.4 执行JavaScript

# ==================== 滚动页面 ==================== # 滚动到页面底部 driver.execute_script('window.scrollTo(0, document.body.scrollHeight)') # 滚动到页面顶部 driver.execute_script('window.scrollTo(0, 0)') # 滚动到指定元素位置 element = driver.find_element(By.ID, 'footer') driver.execute_script('arguments[0].scrollIntoView();', element) # ==================== 获取页面信息 ==================== # 获取页面标题 title = driver.execute_script('return document.title') # 获取页面URL url = driver.execute_script('return window.location.href') # 获取页面高度 height = driver.execute_script('return document.body.scrollHeight') # ==================== 操作隐藏元素 ==================== # 对于隐藏的input,可以直接用JS赋值 driver.execute_script("arguments[0].value='test';", hidden_input) # ==================== 处理alert弹窗 ==================== # 获取alert文本 alert_text = driver.execute_script("return document.querySelector('.modal').textContent") # 关闭alert driver.execute_script("window.confirm = function(){return true;}")

2.5 交互操作

from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains # ==================== 输入框操作 ==================== element.send_keys('文本') # 输入文本 element.send_keys(Keys.RETURN) # 按回车 element.send_keys(Keys.ENTER) # 按回车(与RETURN等价) element.send_keys(Keys.CONTROL, 'a') # 全选 element.send_keys(Keys.BACKSPACE) # 删除 element.clear() # 清空输入框 # ==================== 鼠标操作 ==================== # 单击 element.click() # 右键点击(上下文菜单) ActionChains(driver).context_click(element).perform() # 双击 ActionChains(driver).double_click(element).perform() # 悬停(鼠标移动到元素上) ActionChains(driver).move_to_element(element).perform() # 拖拽 source = driver.find_element(By.ID, 'drag') target = driver.find_element(By.ID, 'drop') ActionChains(driver).drag_and_drop(source, target).perform() # ==================== 键盘操作 ==================== # 组合键 ActionChains(driver).key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询