使用用户脚本捕获页面 xmlhttp 请求

2022-01-15 00:00:00 xmlhttprequest ajax userscripts

我有一个用户脚本(用于 chrome 和 FF),它为页面添加了重要功能,但最近由于开发人员在页面中添加了一些 AJAX 而被破坏.我想修改脚本以侦听页面 xmlhttp 请求,以便我可以根据页面正在接收的 JSON 格式的 responseText 动态更新我添加的内容.

I have a user script (for chrome and FF) that adds significant functionality to a page, but has recently been broken because the developers added some AJAX to the page. I would like to modify the script to listen to the pages xmlhttp requests, so that I can update my added content dynamically, based on the JSON formatted responseText that the page is receiving.

搜索发现了许多应该工作的功能,并且在控制台中运行时可以工作.但是,它们不会从用户脚本的上下文中执行任何操作.

A search has turned up many functions that SHOULD work, and do work when run in the console. However they do nothing from the context of a user script.

(function(open) {

    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

        this.addEventListener("readystatechange", function() {
            console.log(this.readyState);
        }, false);

        open.call(this, method, url, async, user, pass);
    };

})(XMLHttpRequest.prototype.open);

来自:如何我可以从 Greasemonkey 脚本中截获 XMLHttpRequests 吗?

这在控制台中完美运行,我可以将 this.readyState 更改为 this.responseText 并且效果很好(尽管在脚本中我需要它来打开JSON 数据转换成一个对象,然后让我在用户脚本中对其进行操作.不仅仅是写入控制台).但是,如果我将其粘贴到用户脚本中,则不会发生任何事情.用户脚本中的事件处理程序似乎没有检测到页面上的 xmlhttp 请求.

This works perfectly in the console, I can change this.readyState to this.responseText and it works great (though in the script I will need it to turn the JSON data into an object, and then let me manipulate it within the userscript. Not just write to the console). However if I paste it into a userscript nothing happens. The xmlhttp requests on the page do not seem to be detected by the event handler in the userscript.

执行请求的页面正在使用 jquery $.get() 函数,如果这可能与它有关的话.虽然我不这么认为.

The page doing the requesting is using the jquery $.get() function, if that could have anything to do with it. Though I don't think it does.

我无法想象没有办法,似乎任何在 AJAX 页面上运行的用户脚本都需要这种能力.

I can't imagine that there isn't a way, seems like any userscript running on an AJAX page would want this ability.

推荐答案

由于页面使用了$.get(),因此拦截请求更加容易.使用 ajaxSuccess().

Since the page uses $.get(), it's even easier to intercept requests. Use ajaxSuccess().

这将在 Greasemonkey(Firefox) 脚本中工作:
片段 1:

This will work in a Greasemonkey(Firefox) script:
Snippet 1:

unsafeWindow.$('body').ajaxSuccess (
    function (event, requestData)
    {
        console.log (requestData.responseText);
    }
);

假设页面以正常方式使用jQuery($定义等).

Assuming the page uses jQuery in the normal way ($ is defined, etc.).


这应该适用于 Chrome 用户脚本(以及 Greasemonkey):
片段 2:

This should work in a Chrome userscript (as well as Greasemonkey):
Snippet 2:

function interceptAjax () {
    $('body').ajaxSuccess (
        function (event, requestData)
        {
            console.log (requestData.responseText);
        }
    );
}

function addJS_Node (text, s_URL, funcToRun) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ    = D.getElementsByTagName('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}

addJS_Node (null, null, interceptAjax);

<小时><小时><小时>

回复:




Re:

但是我如何将这些数据获取到脚本中?...(这样我可以)稍后在脚本中使用这些数据."

"But how then do I get that data to the script? ... (So I can) use the data later in the script."

这适用于 Greasemonkey(Firefox);它也可能适用于 Chrome 的 Tampermonkey:
片段 3:

This works in Greasemonkey(Firefox); it might also work in Chrome's Tampermonkey:
Snippet 3:

function myAjaxHandler (requestData) {
    console.log ('myAjaxHandler: ', requestData.responseText);
}

unsafeWindow.$('body').ajaxSuccess (
    function (event, requestData) {
        myAjaxHandler (requestData);
    }
);


但是,如果不这样做,那么您将无法(轻松地)在 Chrome 用户脚本和目标页面之间共享 JS 信息——这是设计使然.


But, if it doesn't then you cannot share JS information (easily) between a Chrome userscript and the target page -- by design.

通常您所做的是注入整个用户脚本,以便所有内容都在页面范围内运行.像这样:
片段 4:

Typically what you do is inject your entire userscript, so that everything runs in the page scope. Like so:
Snippet 4:

function scriptWrapper () {

    //--- Intercept Ajax
    $('body').ajaxSuccess (
        function (event, requestData) {
            doStuffWithAjax (requestData);
        }
    );

    function doStuffWithAjax (requestData) {
        console.log ('doStuffWithAjax: ', requestData.responseText);
    }

    //--- DO YOUR OTHER STUFF HERE.
    console.log ('Doing stuff outside Ajax.');
}

function addJS_Node (text, s_URL, funcToRun) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ    = D.getElementsByTagName('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}

addJS_Node (null, null, scriptWrapper);

相关文章