使用 Selenium-Wire 捕获和分析前端网络请求

使用 Selenium-Wire 捕获和分析前端网络请求

标准 selenium 并非为直接捕获 api 请求设计,但 `selenium-wire` 扩展了其功能,允许开发者在自动化测试中拦截、检查和分析浏览器与服务器之间的所有网络流量。本文将详细介绍如何利用 `selenium-wire` 捕获特定 api 请求及其 json 响应数据,从而在不改变页面 url 的情况下,获取前端与后端交互的深层信息,适用于需要监控或验证 api 通信的自动化场景。

理解 Selenium 在 API 捕获中的局限性

Selenium 主要是一个浏览器自动化工具,用于模拟用户与网页的交互,如点击、输入、导航等。它关注的是用户可见的界面行为和页面状态变化。虽然可以通过 WebDriver 的日志(如 performance 日志)或执行 CDP(Chrome DevTools Protocol)命令来尝试获取网络请求信息,但这些方法通常较为复杂、不够直观,且可能依赖于特定浏览器或版本,维护成本较高。

当需求是捕获由前端行为(例如点击按钮)触发的后端 API 请求及其响应数据,特别是当页面 URL 不变而仅有 API 端点发生交互时,标准 Selenium 的能力显得捉襟见肘。此时,我们需要一个更专业的工具来直接监听和解析网络流量。

引入 Selenium-Wire:网络流量的监听器

selenium-wire 是一个 Python 库,它通过在 Selenium WebDriver 和浏览器之间设置一个代理(Proxy),从而能够拦截和检查所有流经浏览器的网络请求和响应。这使得开发者可以轻松地访问请求头、请求体、响应头和响应体,并对它们进行过滤和分析。

Selenium-Wire 的核心优势:

  • 透明代理: 无需额外配置浏览器代理,selenium-wire 会自动处理。
  • 全面捕获: 能够捕获所有类型的网络请求,包括 XHR/Fetch 请求、图片、CSS、JS 等。
  • 易于访问: 提供简洁的 API 来访问请求和响应的各个部分。
  • 灵活过滤: 可以根据 URL、方法、头信息等条件过滤请求。

安装与配置

首先,需要安装 selenium-wire 库。

千面视频动捕

千面视频动捕是一个AI视频动捕解决方案,专注于将视频中的人体关节二维信息转化为三维模型动作。

27

查看详情

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
    # 
    # 
    # 
    #     Test Page
    #     
    #         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));
    #         }
    #     
    # 
    # 
    #     

API Data Loader

# #

#
#
# ```
# 然后你可以用一个本地服务器(如 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 响应数据。")

示例代码解析

  1. 导入必要的库: selenium_wire.webdriver 是核心,用于创建支持网络监听的 WebDriver 实例。其他如 By, WebDriverWait, EC 用于 Selenium 常见操作,json 用于处理 JSON 响应,time 用于简单的等待,logging 用于输出信息。
  2. capture_api_response 函数: 封装了整个捕获逻辑,提高了代码的复用性。
  3. WebDriver 初始化: driver = webdriver.Chrome(options=options) 创建了一个 selenium-wire 增强的 Chrome WebDriver 实例。所有通过此 driver 发起的请求都会被 selenium-wire 代理。
  4. 访问页面: driver.get(start_url) 导航到目标网页。
  5. 清除请求记录: driver.delete_all_requests() 是一个非常关键的步骤。在执行可能触发 API 请求的操作之前调用它,可以确保 driver.requests 列表中只包含后续操作产生的网络流量,避免混淆。
  6. 模拟用户操作: 使用 WebDriverWait 和 EC 确保元素加载并可点击,然后通过 element_to_click.click() 模拟用户点击操作,这个操作预期会触发一个 API 请求。
  7. 等待请求完成: time.sleep(5) 提供了一个简单的等待机制,确保浏览器有足够的时间来发送请求并接收响应。在实际应用中,更健壮的方法可能是等待某个特定的 DOM 元素出现或消失,或者使用 WebDriverWait 结合自定义的 expected_conditions 来判断 API 请求是否完成。
  8. 遍历并过滤请求:

    • for request in driver.requests: 遍历 selenium-wire 捕获到的所有请求。
    • if request.response and api_url_part in request.url: 这是一个重要的过滤条件。它首先检查请求是否有对应的响应(即请求已完成),然后检查请求的 URL 是否包含我们关注的 API 端点的一部分。
    • if 'application/json' in content_type: 进一步过滤,确保响应是 JSON 格式。
    • body = request.response.body.decode('utf-8') 获取响应体,它通常是字节流,需要解码成字符串。
    • json_data = json.loads(body) 将字符串解析成 Python 字典。
  9. 错误处理与日志: 使用 try...except 块处理 JSON 解析错误或其他异常,并利用 logging 模块输出详细的运行信息,便于调试和监控。
  10. 关闭浏览器: driver.quit() 在操作完成后关闭浏览器实例,释放资源。

注意事项

  • 异步性: 网络请求是异步的。在点击触发 API 的元素后,需要给予浏览器足够的时间来完成请求和响应。简单的 time.sleep() 并非最佳实践,应考虑更智能的等待策略,例如等待特定数据出现在页面上,或者等待 driver.requests 列表中出现符合条件的请求。
  • 请求过滤: 根据实际需求,可以组合多种过滤条件(如 request.method, request.headers, request.body 等)来精确匹配目标 API 请求。
  • 响应体编码: 响应体 request.response.body 是字节数据,需要根据实际编码(通常是 UTF-8)进行解码。
  • 代理配置: selenium-wire 默认会为 WebDriver 配置一个代理。如果你的测试环境有特殊的网络代理需求,可以通过 selenium_wire.webdriver.Chrome(seleniumwire_options={'proxy': ...}) 来进行配置。
  • 资源清理: 每次执行完测试后,务必调用 driver.quit() 关闭浏览器实例,防止资源泄露。
  • 无头模式: 在 CI/CD 环境中,通常会使用无头模式 (options.add_argument('--headless')) 运行浏览器,这不会影响 selenium-wire 的功能。

总结

selenium-wire 极大地扩展了 Selenium 在网络流量监控方面的能力,使其成为一个强大的工具,不仅能模拟用户交互,还能深入洞察前端与后端之间的通信。通过本文介绍的方法,开发者可以轻松地在自动化测试中捕获和分析 API 请求及其响应,这对于验证数据流、检测后端问题或在复杂的单页应用中提取关键数据至关重要。掌握 selenium-wire 将使你的自动化测试和数据抓取能力提升到一个新的水平。

以上就是使用 Selenium-Wire 捕获和分析前端网络请求的详细内容,更多请关注昆居客【www.kunjuke.com】。

相关推荐:

vivo浏览器网页图片显示不出来怎么办_vivo浏览器网络请求优化

vivo浏览器图片不显示可按五步修复:一、关闭无图模式;二、清除缓存与网站数据;三、关闭广告过滤并允许图片权限;四、重置DNS并切换网络;五、禁用硬件加速及GPU渲染。 如果您在使用vivo浏览器访问网页时发现图片无法正常显示,可能是由于网络请求被拦截、DNS解析失败、本地缓存异常、权限限制或加载策略误启用所致。以下是针对该问题的多种修复方法: 一、检查并关闭无图模式 无图模式会主动屏蔽所有图片资...

如何用千问做产品评论的自动分析?

产品评论自动分析有四种方法:一、零样本情感与维度分类,用通义千问2.5-7B-Instruct按预设维度输出正/负/未提及;二、基于Qwen3-Embedding-4B的无监督聚类,结合UMAP与HDBSCAN发现隐性主题;三、用Qwen3-Reranker-0.6B对业务问题做细粒度相关性重排序;四、跨平台多源评论聚合,对比识别本品独有短板或优势。 ☞☞☞AI 智能聊天, 问答助手, AI 智能...
· AI · 43126

Duck.ai在竞品文案分析中的使用:让AI对比分析竞争对手文案策略的实践教程

Duck.ai提供五维竞品文案分析法:一、结构化语义对比;二、角色驱动策略归因;三、平台语境反向推演;四、合规红线交叉校验;五、动态策略时间轴演化。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ 如果您希望深入理解竞争对手在文案层面的表达逻辑、价值锚点与用户触达策略,但人工逐条比对耗时低效且易遗漏隐性模式,则可借助Duck.ai对多源竞品文...
· AI · 127644

千问大模型怎么用来做舆情监控分析?社交媒体舆论分析自动化方案

针对社交媒体品牌口碑自动分析,可选用五种方法:一、Qwen2.5-0.5B-Instruct本地轻量情感分类;二、Qwen3-1.7B构建流式舆情监控管道;三、Qwen3-Reranker-0.6B实现热点话题精准排序;四、Qwen2.5-7B-Instruct部署危机预警闭环系统;五、OpenClaw+Qwen3.5-9B实现关键词驱动的监测与发布联动。 ☞☞☞AI 智能聊天, 问答助手, AI...
· AI · 237399

如何用Kimi分析公众号文章趋势_利用Kimi联网数据分析

Kimi可实时抓取分析公众号文章趋势:一、联网检索近7天含关键词的推文并结构化提取元数据;二、批量解析多篇文章的主题聚类与情绪倾向;三、构建30天关键词热度时间序列图谱;四、拆解10w+爆文结构并反向生成优化方案。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ 如果您希望掌握公众号内容的传播规律与读者兴趣变化,但缺乏对海量文章数据的实时洞察...
· AI · 188988

QClaw怎么生成接口幂等性处理代码?API重复请求防护方案

QClaw可生成四类幂等代码:一、基于Redis Token校验;二、数据库UPSERT防重;三、请求指纹哈希去重;四、Redisson分布式锁增强型幂等,覆盖不同业务场景需求。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ 如果您在开发API接口时遇到重复提交导致数据异常的问题,QClaw可直接生成符合业务场景的幂等性处理代码。以下是具体...

百度浏览器如何精细化管理百度地图的位置请求权限_百度定位授权单次允许

可通过系统级权限管理实现百度浏览器访问百度地图时的单次定位授权:Android启用“仅本次允许”,iOS改用Safari/Chrome临时授权,或跳转百度地图App复用其权限,调试场景可用模拟位置工具人工控制。 如果您在使用百度浏览器访问百度地图相关服务时,希望对位置请求实施更精细的控制,而非始终允许或完全禁止,则需通过系统级权限管理实现单次授权或按需授权机制。以下是实现该目标的具体操作路径: 一...

谷歌浏览器开发者工具怎么抓包_谷歌浏览器网络请求分析教程

需用Chrome Network面板抓包分析网络请求:先启用面板并开启录制,再按类型/关键词筛选目标请求,接着查看请求头、响应内容及状态码定位问题,最后可导出HAR文件保存记录,并通过禁用缓存、保留日志等措施应对异常。 如果您需要观察网页与服务器之间传输的数据内容,例如API接口调用、资源加载过程或错误请求细节,则必须借助Chrome浏览器内置的Network面板进行实时捕获和分析。以下是完成抓包...