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)
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值