Duolingo用户脚本无法拦截多数网络请求问题排查
问题修复方案
完整修复脚本
// ==UserScript== // @name Duolingo Request Logger // @namespace http://tampermonkey.net/ // @version 0.2 // @description Log all XHR and fetch requests on Duolingo // @author You // @match https://www.duolingo.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=duolingo.com // @grant GM_log // @run-at document-start // ==/UserScript== (function() { 'use strict'; console.log('Request logger active'); // 拦截XMLHttpRequest请求 const originalXhrOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this._requestUrl = url; console.log('XHR open:', method, url); return originalXhrOpen.apply(this, arguments); }; const originalXhrSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(body) { console.log('XHR send:', this._requestUrl); return originalXhrSend.apply(this, arguments); }; // 拦截fetch请求 const originalFetch = window.fetch; window.fetch = function(resource, options) { // 兼容resource为字符串URL或Request对象的情况 const requestUrl = typeof resource === 'string' ? resource : resource.url; console.log('Fetch request:', requestUrl); return originalFetch.apply(this, arguments); }; })();
关键修复点说明
强制脚本早加载
必须添加@run-at document-start,确保脚本在页面任何业务代码执行前注入,这样才能完整覆盖原生的XMLHttpRequest和fetch方法,避免页面提前缓存未被拦截的原生方法引用。修复fetch拦截逻辑
原fetch拦截代码存在两个致命问题:- fetch的第一个参数既可以是字符串URL,也可以是
Request对象,直接访问request.url会在参数为字符串时报错,需要先判断类型再提取URL。 - 无需将fetch包装为
async函数,原生fetch本身返回Promise,保持原有调用逻辑即可。
- fetch的第一个参数既可以是字符串URL,也可以是
补充fetch拦截
现代网站(包括Duolingo)已大量使用fetch API替代XMLHttpRequest,仅拦截XHR会漏掉绝大多数请求,必须同时覆盖两种请求方式。提升XHR拦截的鲁棒性
通过实例属性_requestUrl存储请求地址,避免与页面可能存在的其他属性冲突,确保日志输出的准确性。
验证方法
刷新Duolingo页面后查看浏览器控制台,即可看到包括/YYYY-MM-DD/sessions在内的所有XHR和fetch请求日志。
内容的提问来源于stack exchange,提问作者chocojunkie
相关产品推荐
相关产品推荐

