Chrome 谷歌插件开发 监听网页请求和响应数据

manifest.json 中的权限

"permissions": [
    "proxy",
    "unlimitedStorage",
    "<all_urls>",
    "declarativeContent",
    "browsingData",
    "cookies",
    "tabs",
    "storage",
    "notifications",
    "webRequest",
    "webRequestBlocking",
    "http://*/*",
    "https://*/*",
    "debugger",
    "activeTabs"
  ],

一、使用 webRequest

使用权限 "webRequest","webRequestBlocking"
在背景页中拦截并发出请求获取数据,
webRequest只能拦截到请求,想要获取响应数据可以重发一次请求

const axios = require('axios');
//封装get请求
function axiosGet(url){
    return new Promise((res,rej)=>{
        axios.get(url).then(e=>{
            res(e)
        }).catch(e=>{
            rej(e)
        })
    })
}

/**
 * 拦截请求并修改指定请求头信息
 */
chrome.webRequest.onBeforeSendHeaders.addListener(async function (details) {
		// 可以自行添加头部
        details.requestHeaders.push({name: 'Referer', value: 'https://h5.m.taobao.com/'});
        if (details.tabId != -1) {
            if (/getdetail|getdesc/.test(details.url) && !/i=6666/.test(details.url)){
                let res = await axiosGet(`${details.url}&i=6666`)
                console.log('res',res)
            }
        }
        return { requestHeaders: details.requestHeaders };
    }, {
        urls: [
            "*://h5api.m.taobao.com/h5/mtop.taobao.detail.*",
        ]
    }, ['blocking', 'requestHeaders','extraHeaders']
);

二、使用 debugger

使用权限 "debugger","activeTabs"
背景页使用该方法

async function debuggerAttach() {
    let currentTab;
    let version = '1.3';
    let debuggee = ''

    chrome.tabs.query({url: '所要监听页面的url'}, (tabs) => {
        currentTab = tabs[0]
        chrome.debugger.attach({
            tabId: currentTab.id
        }, version, onAttach.bind(null, currentTab.id));
    });

    function onAttach(tabId) {
        if (chrome.runtime.lastError) {
            console.log('onAttach-Error', chrome.runtime.lastError);
            return
        }
        console.log("onAttach-Success");
        chrome.debugger.sendCommand({
            tabId: tabId
        }, "Network.enable");
        chrome.debugger.onEvent.addListener(allEventHandler);
    }

    function allEventHandler(debuggeeId, message, params) {
        debuggee = debuggeeId
        if (currentTab.id !== debuggeeId.tabId) {
            console.log('currentTab.id !== debuggeeId.tabId')
            return;
        }
        if (message === "Network.responseReceived") {
            let url = params?.response?.url
            chrome.debugger.sendCommand({
                tabId: debuggeeId.tabId
            }, "Network.getResponseBody", {
                "requestId": params.requestId
            }, async function (response) {
                    console.log('response======>', response)
                }
            });
        }
    }
    console.log('关闭调试')
    debuggee && chrome.debugger.detach(debuggee)
}
debuggerAttach()

三、使用 ajax_interceptor_manny

该方法只能拦截到 Fetch/XHR 类型 的数据

window.ajax_interceptor_manny = {
    settings: {
      switchOn: false,
      switchQuery:false
    },
    originalXHR: window.XMLHttpRequest,
    myXHR: function() {
      let pageScriptEventDispatched = false;
      const modifyResponse = () => {
        //this.responseText = overrideTxt;
        //this.response = overrideTxt;
        if (pageScriptEventDispatched) {
          return;
        }
        pageScriptEventDispatched = true;
        ajax_interceptor_manny.download(this.responseText, this.responseURL);
      }

      // new 一个原生的 XMLHttpRequest 不需要参数,将 xhr 的属性,都复制给this,暴露到外面
      const xhr = new ajax_interceptor_manny.originalXHR();

      for (let attr in xhr) {
        if (attr === 'onreadystatechange') {
          xhr.onreadystatechange = (...args) => {
            if (this.readyState == 4 && this.status == 200) {
              // 请求成功
              if (ajax_interceptor_manny.settings.switchOn) {
                // 开启拦截
                modifyResponse();
              }
            }
            this.onreadystatechange && this.onreadystatechange.apply(this, args);
          }
          continue;
        } else if (attr === 'onload') {
          xhr.onload = (...args) => {
            // 请求成功
            if (ajax_interceptor_manny.settings.switchOn) {
              // 开启拦截
              modifyResponse();
            }
            this.onload && this.onload.apply(this, args);
          }
          continue;
        }

        if (typeof xhr[attr] === 'function') {
          this[attr] = xhr[attr].bind(xhr);
        } else {
          if (attr === 'responseText' || attr === 'response') {
            var k = "_"+attr;
            Object.defineProperty(this, attr, {
              get: () => this[k] == undefined ? xhr[attr] : this[k],
              set: (val) => this[k] = val,
            });
          } else {
            Object.defineProperty(this, attr, {
              get: () => xhr[attr],
              set: (val) => xhr[attr] = val,
            });
          }
        }
      }
    },
    originalFetch: window.fetch.bind(window),
    myFetch: function(...args) {
      return ajax_interceptor_manny.originalFetch(...args).then((response) => {
        if (response.ok) {
          response.clone().text().then((res) => {
            ajax_interceptor_manny.download(res, response.url);
          }).catch((e) => {
            console.warn(e)
          });
        }
        return response;
      });
    },
    download(data, url) {
      try {
        if (ajax_interceptor_manny.settings.switchOn) {

          if (data && typeof data == "string") {
            data = JSON.parse(data);
            data.url = url;
          }
          if (data){
            //遍历需要捕获的接口
            captureInterfaces.forEach((item)=>{
              if(data.url.indexOf(item) >-1){
                	console.log('data',data)
                }
              }

            })

          }

        }
      } catch (e) {
        console.error("数据获取失败", e);
      }

    },

    setSetting(data) {
      if (typeof data !== "object") {
        return;
      }
      //设置环境
      for (var i in data) {
        ajax_interceptor_manny.settings[i] = data[i];
      }
    },
    init() {
      window.XMLHttpRequest = ajax_interceptor_manny.myXHR;
      window.fetch = ajax_interceptor_manny.myFetch;
    }
  }
  ajax_interceptor_manny.init();
  ajax_interceptor_manny.setSetting({
    switchOn:true
  })

四、拦截 script 类型 数据

可以使用js注入拦截方法,如未获取到可使用setTimeout等待

let jsonp1 = ''
let jsonp2 = ''
window.setTimeout(()=>{
  window.mtopjsonpCopy1 = window.mtopjsonp1
  window.mtopjsonp1 = function(res) {
    console.log('@@@@@mtopjsonp1',res)
    jsonp1 = res
    window.mtopjsonpCopy1(res)
    window.setTimeout(()=>{
      window.mtopjsonpCopy3 = window.mtopjsonp3
      window.mtopjsonp3 = function(res) {
        console.log('@@@@@mtopjsonp3',res)
        jsonp2 = res
        window.mtopjsonpCopy3(res)
      }
    },200)
  }
},200)
谷歌浏览器扩展插件通常使用HTML、CSS、JavaScript以及API如Chrome APIs来创建,其中一种常见的功能是监听特定的URL请求,并处理响应。为了实现这个功能,你可以按照以下步骤: 1. **背景脚本**:在manifest.json文件中声明`"permissions"`,允许访问网络资源。编写background.js或background.html文件,这里可以设置一个事件处理器,监听`chrome.webRequest.onBeforeSendHeaders`或`chrome.webRequest.onCompleted`等事件。 ```json { "name": "My URL Listener", "version": "1.0", "permissions": ["webRequest", "https://your-target-url/*"], "background": { "scripts": ["background.js"] }, // 其他配置... } ``` 2. **事件处理器**:在background.js中,注册一个函数处理请求。当特定URL的请求发送或完成时,你的函数会被调用。例如,你可以检查请求头或URL是否匹配,然后读取响应内容。 ```javascript chrome.webRequest.onBeforeSendHeaders.addListener( function(details) { if (details.url.includes("your-target-url")) { // 执行操作,比如修改请求头,然后返回Promise等待服务器响应 return {requestHeaders: ...}; } return {cancel: false}; }, {urls: ["<all_urls>"]}, // 监听所有URL ['headers', 'blocking'] ); ``` 3. **响应内容获取**:当请求完成后,通过`chrome.webResponse` API获取到响应体,通常会是一个`ReadableStream`,你可以将其转化为字符串或其他格式来输出。 ```javascript chrome.webRequest.onCompleted.addListener(function(details) { if (details.url.includes("your-target-url")) { fetch(details.response.url) .then(response => response.text()) .then(data => console.log('Response content:', data)); } }, {urls: ["<all_urls>"]}, ['response']); // 或者使用fetch API直接操作响应 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值