You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Playwright的CDP会话提取Network面板请求发起链元素?

请求发起链中Initiator URL获取不一致的问题

场景说明

我需要提取网络请求的直接父请求URL,例如在Chromium DevTools的Network面板中,某请求https://uk-script.dotmetrics.net/hit.gif?id=13934&url=https%3A%2F%2Fwww.bbc.com%2Fweather%2F1264527&dom=www.bbc.com&r=1686291576433&pvs=1&pvid=f4aaa4fd-2def-4a70-ab77-c4e11e570388&c=true&tzOffset=-330&doorUrl=http%3a%2f%2fuk-script.dotmetrics.net%2fdoor.js%3fd%3dwww.bbc.com%26t%3dweathergnl的直接父请求是https://uk-script.dotmetrics.net/door.js?d=www.bbc.com&t=weathergnl,这正是我要提取的信息。

尝试的方法

我使用Playwright开启CDP会话拦截网络请求,提取每个请求的Network.Initiator对象,代码如下:

const { chromium } = require('playwright');

(async () => {
  // Launch browser with headless set to false
  const browser = await chromium.launch({ headless: false });
  let cnt = 1;

  // Create a new context with CDP enabled
  const context = await browser.newContext({
    devtools: true,
  });

  // Create a new page
  const page = await context.newPage();

  // Enable the CDP session
  const client = await page.context().newCDPSession(page);

  // Enable network interception
  await client.send('Network.enable');

  // Listen for network requests
  client.on('Network.requestWillBeSent', (event) => {
    console.log("::::::::::Network Call "+ cnt +"::::::::::");
    console.log('Request URL: ', event.request.url);
    console.log('\nInitiator: ', event.initiator);
    // console.log('\nReferer URL: ', event.request.headers);
    console.log("\n");
    cnt++;
  });

  // Navigate to the website
  await page.goto('https://www.bbc.com/weather/1264527');

  // Perform any further actions using the CDP session if needed
  // For example, you can use client.send() to interact with the CDP API.
  // Scroll down the page bit by bit
  const SCROLL_AMOUNT = 250; // Adjust the scroll amount as needed
  const pageHeight = await page.evaluate(() => document.documentElement.scrollHeight);

  let currentScroll = 0;
  while (currentScroll < pageHeight) {
    await page.evaluate((scrollAmount) => {
      window.scrollBy(0, scrollAmount);
    }, SCROLL_AMOUNT);
    currentScroll += SCROLL_AMOUNT;
    await page.waitForTimeout(500); // Adjust the timeout as needed
  }
  // Close the browser
  await browser.close();
})();

遇到的问题

针对同一个请求,通过上述代码获取到的Initiator URL和DevTools窗口中显示的不一致,想知道原因,以及有没有其他方法可以获取请求发起链中显示的准确发起者信息。


原因分析

  1. 事件触发时机差异:Network.requestWillBeSent在请求即将发送时触发,此时请求的发起链信息可能还未完全确定。DevTools显示的是请求完成后最终的发起链,信息更完整。
  2. 发起者信息的粒度问题:如果请求由脚本动态发起,CDP返回的initiator对象可能只指向当前执行脚本的上下文URL,而非直接发起请求的具体脚本文件。DevTools会追踪到更细粒度的发起脚本。
  3. Playwright上下文干扰:开启devtools: true可能会影响CDP会话的信息采集逻辑,导致部分细节丢失。

解决方法

方法1:监听Network.requestWillBeSentExtraInfo事件

该事件提供更详细的发起信息,替换原代码中的Network.requestWillBeSent:

client.on('Network.requestWillBeSentExtraInfo', (event) => {
  console.log("::::::::::Network Call "+ cnt +"::::::::::");
  console.log('Request URL: ', event.requestUrl);
  console.log('\nInitiator Info: ', event.initiator);
  console.log("\n");
  cnt++;
});

方法2:使用Playwright原生request事件

Playwright原生API已封装了发起链信息,无需直接操作CDP,使用更简便:

page.on('request', (request) => {
  console.log("::::::::::Network Call "+ cnt +"::::::::::");
  console.log('Request URL: ', request.url());
  console.log('\nInitiator URL: ', request.initiator().url);
  console.log("\n");
  cnt++;
});

方法3:获取完整发起链(请求完成后)

通过Network.getRequestInitiatorChain方法,在请求完成后获取完整的发起链:

client.on('Network.requestFinished', async (event) => {
  const initiatorChain = await client.send('Network.getRequestInitiatorChain', {
    requestId: event.requestId
  });
  console.log("Request URL: ", event.request.url);
  console.log("Full Initiator Chain: ", initiatorChain.chain);
});

注意事项

  • 确保提前调用await client.send('Network.enable')启用网络域。
  • 对于动态加载的内容,可结合page.waitForLoadState('networkidle')等待页面稳定后再采集信息,避免遗漏。

内容的提问来源于stack exchange,提问作者Manoj Raghavendran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:44:53