Playwright 通过 Chrome DevTools Protocol (CDP) 直接控制网络条件

488 阅读3分钟

Playwright 通过 Chrome DevTools Protocol (CDP) 提供了强大的网络模拟功能,可以模拟各种网络条件,如慢速 3G、离线状态、自定义网络延迟等。下面我将介绍常见的网络模拟示例代码并详细解释其原理和参数。

1. 基本网络模拟示例

from playwright.sync_api import sync_playwright

def run(playwright):
    browser = playwright.chromium.launch()
    context = browser.new_context()
    
    # 启用网络模拟
    page = context.new_page()
    
    # 模拟慢速3G网络
    context.set_offline(False)  # 确保在线状态
    context.set_geolocation({"latitude": 51.5074, "longitude": -0.1278})  # 可选:设置地理位置
    
    # 使用CDP直接设置网络条件
    cdp_session = context.new_cdp_session(page)
    cdp_session.send("Network.emulateNetworkConditions", {
        "offline": False,
        "downloadThroughput": 500 * 1024 / 8,  # 500 Kbps
        "uploadThroughput": 250 * 1024 / 8,    # 250 Kbps
        "latency": 400                         # 400ms延迟
    })
    
    page.goto("https://example.com")
    print(page.title())
    
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

2. 预定义网络配置文件

Playwright 提供了一些预定义的网络配置文件:

from playwright.sync_api import sync_playwright

def run(playwright):
    browser = playwright.chromium.launch()
    context = browser.new_context()
    
    # 使用预定义的网络配置
    context.set_offline(False)
    
    # 可选预定义配置:
    # - "slow-3g"
    # - "fast-3g"
    # - "regular-3g"
    # - "4g"
    # - "offline"
    context.set_network_conditions("slow-3g")
    
    page = context.new_page()
    page.goto("https://example.com")
    print(page.title())
    
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

3. 高级网络控制

from playwright.sync_api import sync_playwright

def run(playwright):
    browser = playwright.chromium.launch()
    context = browser.new_context()
    
    # 启用网络拦截和修改
    page = context.new_page()
    
    # 路由请求并修改
    def handle_route(route):
        if "google-analytics.com" in route.request.url:
            # 阻止分析请求
            route.abort()
        else:
            route.continue_()
    
    page.route("**/*", handle_route)
    
    # 自定义网络条件
    cdp_session = context.new_cdp_session(page)
    cdp_session.send("Network.enable")
    cdp_session.send("Network.emulateNetworkConditions", {
        "offline": False,
        "downloadThroughput": 1.5 * 1024 * 1024 / 8,  # 1.5 Mbps
        "uploadThroughput": 750 * 1024 / 8,           # 750 Kbps
        "latency": 150                                # 150ms延迟
    })
    
    page.goto("https://example.com")
    
    # 获取网络指标
    metrics = page.evaluate("""() => {
        return {
            loadEventEnd: window.performance.timing.loadEventEnd - window.performance.timing.navigationStart,
            domContentLoaded: window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart
        };
    }""")
    print(f"Page load time: {metrics['loadEventEnd']}ms")
    
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

1. CDP (Chrome DevTools Protocol) 会话

context.new_cdp_session(page) 创建了一个直接与浏览器 DevTools 协议通信的会话。通过这个会话,我们可以发送原始 CDP 命令来精确控制浏览器行为。

2. Network.emulateNetworkConditions 参数

  • offline (boolean): 是否模拟离线状态
  • downloadThroughput (number): 下载吞吐量,单位是字节/秒
    • 例如 500 Kbps = 500 * 1024 / 8 = 64000 字节/秒
  • uploadThroughput (number): 上传吞吐量,单位是字节/秒
    • 例如 250 Kbps = 250 * 1024 / 8 = 32000 字节/秒
  • latency (number): 延迟时间,单位是毫秒

3. 预定义网络配置

Playwright 内置的网络配置对应的实际参数:

  • offline:
    • downloadThroughput: 0
    • uploadThroughput: 0
    • latency: 0
  • slow-3g:
    • downloadThroughput: 500 * 1024 / 8
    • uploadThroughput: 500 * 1024 / 8
    • latency: 2000
  • fast-3g:
    • downloadThroughput: 1.6 * 1024 * 1024 / 8
    • uploadThroughput: 750 * 1024 / 8
    • latency: 150
  • 4g:
    • downloadThroughput: 9 * 1024 * 1024 / 8
    • uploadThroughput: 9 * 1024 * 1024 / 8
    • latency: 20

4. 网络路由拦截

page.route() 方法允许拦截和修改网络请求:

  • route.abort(): 中止请求
  • route.continue_(): 继续原始请求
  • route.fulfill(): 使用自定义响应完成请求

5. 性能指标测量

通过 page.evaluate() 执行 JavaScript 可以获取页面性能指标:

  • navigationStart: 导航开始时间
  • loadEventEnd: 加载事件结束时间
  • domContentLoaded: DOM 内容加载完成时间

实际应用场景

  1. 测试页面在不同网络条件下的表现
  2. 验证离线功能是否正常工作
  3. 测量页面加载性能
  4. 阻止不必要的第三方请求以提高测试速度
  5. 模拟地理位置和网络条件组合测试

通过这些网络模拟功能,我们可以全面测试网站在各种网络环境下的表现,确保良好的用户体验。