通过浏览器插件cdp协议获取网页api部分网址响应数据原理(mv3版)

动作开发 · 3328 次浏览
涛涛涛 创建于 6天11小时前

通过浏览器cdp协议中的实现
1. Network.responseReceived 事件
2. Network.loadingFinished 事件
3. Network.getResponseBody 方法

//.js 
const aURL = '{监控的url}';//需要的监控网址URL
let debuggingTabId = null;//连接tabid
let networkEventListener = null;//监控函数
var shuju=null;//响应的数据
const requestMap = new Map();//筛选requestId 
// ===================================================================
// 核心修改:监听 detach 事件,这是处理“手动断开”的关键
// ===================================================================
chrome.debugger.onDetach.addListener((source, reason) => {
  console.log(`断开: ${reason}.`);
  
  // 检查这个分离事件是否来自我们正在调试的标签页
  if (source.tabId === debuggingTabId) {
    // 执行清理操作
    performCleanup();
  }
});

// ===================================================================
// 将清理逻辑封装到独立函数中
// ===================================================================
function performCleanup() {
  if (networkEventListener) {
    chrome.debugger.onEvent.removeListener(networkEventListener);
    networkEventListener = null;
    console.log("清除监控.");
  }
  
  // 重置状态
  debuggingTabId = null;
}


function startDebugging(tabId) {
  if (debuggingTabId) {
    console.log("Already debugging another tab.");
    return;
  }
  debuggingTabId = tabId;

  // 步骤 1: 附加调试器
  chrome.debugger.attach({ tabId }, '1.3', () => {
    if (chrome.runtime.lastError) {
      console.error("Step 1 Failed: Attach debugger", chrome.runtime.lastError.message);
      chrome.runtime.sendMessage({ action: 'error', error: `Failed to attach: ${chrome.runtime.lastError.message}` });
      // 如果附加失败,也要清理状态
      performCleanup();
      return;
    }
    console.log("连接开始");

networkEventListener = (source, method, params) => {
  // 确保事件来自我们正在调试的标签页
  if (source.tabId !== debuggingTabId) return;

  // --- 步骤 1: 在收到响应头时,记录请求信息 ---
  if (method === 'Network.responseReceived') {
    const { requestId, response } = params;
    // 检查 URL 是否是我们关心的
    if (response.url.includes(aURL)) {
      console.log(`[记录] 找到目标请求,Request ID: ${requestId}, URL:${response.url}`);
      // 将 requestId 和 URL 存入 Map
      requestMap.set(requestId, response.url);
    }
  }

  // --- 步骤 2: 在请求完全加载后,获取响应体 ---
  if (method === 'Network.loadingFinished') {
    const { requestId } = params;
    
    // 从 Map 中查找这个 requestId 是否是我们关心的
    const targetUrl = requestMap.get(requestId);

    if (targetUrl) {
      console.log(`[处理] 目标请求加载完成,Request ID: ${requestId}`);

      // 步骤 3: 调用 getResponseBody 获取响应体
      chrome.debugger.sendCommand(
        source,
        'Network.getResponseBody',
        { requestId: requestId },
        (result) => {
          // 步骤 4: 处理响应体
          if (chrome.runtime.lastError) {
            console.error("获取响应体失败:", chrome.runtime.lastError.message);
            chrome.runtime.sendMessage({ action: 'error', error: `Failed to get body: ${chrome.runtime.lastError.message}` });
            // 即使失败也要清理 Map
            requestMap.delete(requestId);
            return;
          }

          console.log("成功获取响应数据!");
          
          let bodyContent = result.body;
          if (result.base64Encoded) {
            // 如果是二进制内容(如图片),通常需要解码或特殊处理
            // 这里只做简单提示
            bodyContent = `二进制内容 (Base64): ${result.body.substring(0, 100)}...`;
            console.warn("响应体是 Base64 编码的二进制数据。");
          }
          
          // 在这里处理你的数据
          try {
            shuju = JSON.parse(bodyContent);
            console.log("处理后的数据:", shuju);

          } catch (e) {
            console.error("解析 JSON 失败:", e);
            console.log("原始响应体:11", bodyContent);
          }
          
          // 【重要】处理完成后,从 Map 中移除该请求,防止内存泄漏
          requestMap.delete(requestId);
        }
      );
    }
  }
};
    chrome.debugger.onEvent.addListener(networkEventListener);


    // 步骤 3: 启用 Network 域
    chrome.debugger.sendCommand({ tabId }, 'Network.enable', {}, () => {
      if (chrome.runtime.lastError) {
        console.error("Step 3 Failed: Enable Network domain", chrome.runtime.lastError.message);
        // 如果启用失败,主动断开,onDetach 会处理清理
        chrome.debugger.detach({ tabId });
        return;
      }
      console.log("3333");
    });
  });
}

function detachDebugger() {
    if (debuggingTabId) {
      console.log("主动断开");
      chrome.debugger.detach({ tabId: debuggingTabId });
      performCleanup();
    }
}

 

涛涛涛 最后更新于 2025/10/23

侧耳倾听& 6天8小时前 :

大佬这个咋用呢,浏览器控制选  运行后台脚本(MV2版扩展) 吗

侧耳倾听& 最后更新于 6天8小时前
涛涛涛 回复 侧耳倾听& 5天19小时前 :

已现浏览器插件的模式,不太好将其封装成子程序调用,如果你对浏览器插件开发和请求响应有研究或有这方面的知识储备,我可以提供思路,你可以自己尝试封装调用

侧耳倾听& 回复 涛涛涛 5天14小时前 :

就是不会这个,看来只能放弃了.0.0.

涛涛涛 回复 侧耳倾听& 5天13小时前 :


涛涛涛 最后更新于 5天10小时前
涛涛涛 回复 侧耳倾听& 2天10小时前 :

这个差不多构建好了,如果需要使用的话,留一个联系方式,我给你说一下,暂不公布

涛涛涛 最后更新于 2天10小时前
侧耳倾听& 回复 涛涛涛 1天17小时前 :

好的,大佬我加你了

回复内容
涛涛涛 5天10小时前
#1


涛涛涛 最后更新于 2天10小时前
回复主贴