
标准 selenium 并非为直接捕获 api 请求设计,但 `selenium-wire` 扩展了其功能,允许开发者在自动化测试中拦截、检查和分析浏览器与服务器之间的所有网络流量。本文将详细介绍如何利用 `selenium-wire` 捕获特定 api 请求及其 json 响应数据,从而在不改变页面 url 的情况下,获取前端与后端交互的深层信息,适用于需要监控或验证 api 通信的自动化场景。
Selenium 主要是一个浏览器自动化工具,用于模拟用户与网页的交互,如点击、输入、导航等。它关注的是用户可见的界面行为和页面状态变化。虽然可以通过 WebDriver 的日志(如 performance 日志)或执行 CDP(Chrome DevTools Protocol)命令来尝试获取网络请求信息,但这些方法通常较为复杂、不够直观,且可能依赖于特定浏览器或版本,维护成本较高。
当需求是捕获由前端行为(例如点击按钮)触发的后端 API 请求及其响应数据,特别是当页面 URL 不变而仅有 API 端点发生交互时,标准 Selenium 的能力显得捉襟见肘。此时,我们需要一个更专业的工具来直接监听和解析网络流量。
selenium-wire 是一个 Python 库,它通过在 Selenium WebDriver 和浏览器之间设置一个代理(Proxy),从而能够拦截和检查所有流经浏览器的网络请求和响应。这使得开发者可以轻松地访问请求头、请求体、响应头和响应体,并对它们进行过滤和分析。
首先,需要安装 selenium-wire 库。
立即学习“前端免费学习笔记(深入)”;
pip install selenium-wire
安装完成后,可以在 Python 代码中引入并配置 selenium-wire 的 WebDriver。
from selenium_wire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import json
import time
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def capture_api_response(start_url, element_id_to_click, api_url_part):
"""
使用 selenium-wire 捕获点击元素后触发的 API 请求及其 JSON 响应。
Args:
start_url (str): 浏览器起始访问的 URL。
element_id_to_click (str): 需要点击的元素的 ID。
api_url_part (str): 目标 API URL 中包含的特定字符串,用于过滤请求。
Returns:
dict: 如果找到目标 API 的 JSON 响应,则返回解析后的字典;否则返回 None。
"""
# 配置 WebDriver 选项
options = webdriver.ChromeOptions()
# 可以根据需要添加其他选项,例如无头模式
# options.add_argument('--headless')
# options.add_argument('--disable-gpu')
# 配置 selenium-wire 的 WebDriver
# service = Service(executable_path='/path/to/chromedriver') # 如果 chromedriver 不在 PATH 中,需要指定路径
driver = webdriver.Chrome(options=options)
driver.set_page_load_timeout(30) # 设置页面加载超时时间
found_data = None
try:
logger.info(f"正在访问 URL: {start_url}")
driver.get(start_url)
# 清除所有历史请求,确保只捕获本次操作产生的流量
driver.delete_all_requests()
logger.info("已清除所有历史网络请求。")
# 等待元素可点击并执行点击操作
wait = WebDriverWait(driver, 10)
element_to_click = wait.until(EC.element_to_be_clickable((By.ID, element_id_to_click)))
logger.info(f"找到元素 '{element_id_to_click}',准备点击。")
element_to_click.click()
logger.info(f"已点击元素 '{element_id_to_click}'。")
# 等待一段时间,让 API 请求有足够的时间完成并响应
# 实际项目中,可能需要更智能的等待机制,例如等待某个特定的 DOM 元素出现或消失
time.sleep(5)
logger.info("等待 5 秒以捕获网络请求。")
# 遍历所有捕获到的请求
for request in driver.requests:
# 确保请求有响应,并且响应 URL 包含目标 API 的部分
if request.response and api_url_part in request.url:
logger.info(f"捕获到潜在目标API请求: {request.url}")
# 检查响应内容类型是否为 JSON
content_type = request.response.headers.get('Content-Type', '')
if 'application/json' in content_type:
try:
# 获取响应体并解码为 UTF-8 字符串,然后解析为 JSON
body = request.response.body.decode('utf-8')
json_data = json.loads(body)
logger.info(f"成功捕获并解析目标API JSON响应: {request.url}")
logger.info(f"响应数据示例: {json_data}")
found_data = json_data
break # 找到目标数据后即可停止遍历
except json.JSONDecodeError as e:
logger.warning(f"警告: 捕获到 JSON 类型响应但解析失败,URL: {request.url}, 错误: {e}")
except Exception as e:
logger.error(f"处理响应体时发生未知错误,URL: {request.url}, 错误: {e}")
else:
logger.info(f"捕获到非 JSON 响应,URL: {request.url}, Content-Type: {content_type}")
if not found_data:
logger.info(f"未捕获到包含 '{api_url_part}' 的目标API请求及其 JSON 响应。")
except Exception as e:
logger.error(f"在执行过程中发生错误: {e}")
finally:
driver.quit()
logger.info("浏览器已关闭。")
return found_data
# --- 示例用法 ---
if __name__ == "__main__":
# 替换为你的实际场景信息
example_start_url = "https://www.example.com/data_page" # 假设你的页面URL
example_element_id = "loadDataButton" # 假设点击这个ID的按钮会触发API请求
example_api_url_part = "/api/v1/getData" # 假设你的API路径包含这个部分
# 模拟一个简单的 HTML 页面,用于测试
# 你需要手动创建一个这样的 HTML 文件或者有一个真实的页面
# 例如,创建一个 `test_page.html` 文件:
# ```html
# <!DOCTYPE html>
# <html>
# <head>
# <title>Test Page</title>
# <script>
# function loadData() {
# fetch('/api/v1/getData', { method: 'GET' })
# .then(response => response.json())
# .then(data => {
# document.getElementById('result').innerText = JSON.stringify(data, null, 2);
# console.log('Data loaded:', data);
# })
# .catch(error => console.error('Error:', error));
# }
# </script>
# </head>
# <body>
# <h1>API Data Loader</h1>
# <button id="loadDataButton" onclick="loadData()">Load Data</button>
# <pre id="result"></pre>
# </body>
# </html>
# ```
# 然后你可以用一个本地服务器(如 Python 的 http.server)来提供这个文件
# 并在 `example_start_url` 中使用 `http://localhost:8000/test_page.html`
# 注意:为了让此示例代码运行,你需要有一个真实的网页和 API 端点。
# 如果只是为了演示 selenium-wire 的功能,可以访问一个已知会触发 AJAX 请求的公共网站,
# 并调整 element_id_to_click 和 api_url_part。
# 假设我们有一个本地测试服务器运行在 8000 端口,提供 test_page.html
# example_start_url = "http://localhost:8000/test_page.html"
# example_element_id = "loadDataButton"
# example_api_url_part = "/api/v1/getData"
# 运行捕获函数
api_response_data = capture_api_response(
start_url=example_start_url,
element_id_to_click=example_element_id,
api_url_part=example_api_url_part
)
if api_response_data:
print("\n最终捕获到的 API 响应数据:")
print(json.dumps(api_response_data, indent=2, ensure_ascii=False))
else:
print("\n未能成功捕获到目标 API 响应数据。")
selenium-wire 极大地扩展了 Selenium 在网络流量监控方面的能力,使其成为一个强大的工具,不仅能模拟用户交互,还能深入洞察前端与后端之间的通信。通过本文介绍的方法,开发者可以轻松地在自动化测试中捕获和分析 API 请求及其响应,这对于验证数据流、检测后端问题或在复杂的单页应用中提取关键数据至关重要。掌握 selenium-wire 将使你的自动化测试和数据抓取能力提升到一个新的水平。
以上就是使用 Selenium-Wire 捕获和分析前端网络请求的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号