1

站点http://project-gc.com/Statistics/TopFavWilson根据通过 ajax 设置的过滤器查看数据。

我可以将此数据视为条形图。(我已登录并通过身份验证)

但我想保存这些数据以导入到例如电子表格程序中。我需要 Fav%Wilson 积分(也在 ajaxresponde 中),我无法以不同的方式获得它们。

我考虑过使用greasemonkey 脚本从ajaxcall 之后获取responddata。也许用“waitForKeyElements”?

任何人都可以提出解决方案或给我提示如何解决问题吗?

4

1 回答 1

0

如果您只想监视响应而不进行任何交互,则可以将 XHR 构造函数替换为包装函数,并为每个新创建的实例添加一个事件侦听器。

// ==UserScript==
// @name        ajaxobserver
// @namespace   http://example.com
// @description observes ajax responses
// @include     http://project-gc.com/Statistics/TopFavWilson
// @include     http://project-gc.com/Statistics/TopFavWilson/*
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==



// scope encapsulation in newer GM versions not necessary, nevertheless...
(function()
{
  // save constructor
  let XMLHttpRequest = window.XMLHttpRequest;

  // replace constructor function
  window.XMLHttpRequest = function()
  {
    // new instance
    let obj = new XMLHttpRequest();

    // register a listener
    obj.addEventListener('load', function (event)
    {
      console.log('EVENT LISTENER: ajax load: responseText =', event.target.responseText);
    });

    //return the created instance instead of `this`
    return obj;
  };
})();

如果您还想操作结果,您将需要一个代理,或者您已经手动重建整个 XHR 对象作为包装器。这是一个代理示例:

// ==UserScript==
// @name        ajaxmanipulator
// @namespace   http://example.com
// @description observes & manipulate ajax responses
// @include     http://project-gc.com/Statistics/TopFavWilson
// @include     http://project-gc.com/Statistics/TopFavWilson/*
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==

(function()
{
  let
    // a function call handler for onevent functions
    applyEventHandler =
    {
      apply: function(targetFunc, thisArg, [event])
      {
        if
        (
          'readystatechange' === event.type && 4 === event.target.readyState && 200 === event.target.status
          ||
          'load' === event.type
        )
          console.log('EVENT', event.type + ':', event.target.responseText);

        return targetFunc.call(thisArg, event);
      }
    },

    // a function call handler for onevent functions
    applyOpenHandler =
    {                                     // destructuring arguments array into individual named arguments
      apply: function(targetFunc, thisArg, [method, url, async, user, password])
      {
        console.log('open handler:', 'target =', targetFunc, ', thisArg =', thisArg );

        console.log
        ( 'XMLHttpRequest.open\n',
          'method:'  , method,
          'url:'     , url,
          'async:'   , async,
          'user:'    , user,
          'password:', password
        );

        // let's manipulate some argument
        url += '?get-parameter-added-by-proxy';

        // finally call the trapped function in context of thisArg passing our manipulated arguments
        return targetFunc.call(thisArg, method, url, async, user, password);
      }
    },

    // a property handler for XMLHttpRequest instances
    xmlHttpReq_PropertiesHandler =
    {
      // target  : the proxied object (native XMLHttpRequest instance)
      // property: name of the property
      // value   : the new value to assign to the property (only in setter trap)
      // receiver: the Proxy instance

      get:
        function (target, property /*, receiver*/)
        {
          console.log('%cget handler: ', 'color:green', property);

          switch (property)
          {
            case 'responseText':
              // let's return a manipulated string when the property `responseText` is read
              return '<div style="color:red;border:1px solid red">response manipulated by proxy'
                + target.responseText + '</div>';

            case 'open':
              // All we can detect here is a get access to the *property*, which
              // usually returns a function object. The apply trap does not work at this
              // point. Only a *proxied function* can be trapped by the apply trap.
              // Thus we return a proxy of the open function using the apply trap.
              // (A simple wrapper function would do the trick as well, but could be easier
              // detected by the site's script.)
              // We use bind to set the this-context to the native `XMLHttpRequest` instance.
              // It will be passed as `thisArg` to the trap handler.
              return new Proxy(target.open, applyOpenHandler).bind(target);

            default:
              return 'function' === typeof target[property]
                  // function returned by proxy must be executed in slave context (target)
                ? target[property].bind(target)
                  // non-function properties are just returned
                : target[property]
              ;
          }
        },

      set:
        function (target, property, value, receiver)
        {
          try
          {
            console.log('%cset handler: ', 'color:orange', property, '=', value);

            switch (property)
            {
              // Event handlers assigned to the proxy must be stored into the proxied object (slave),
              // so that its prototype can access them (in slave context). Such an access is not trapped by
              // the proxy's get trap. We need to store proxied functions to get ready to observe invokations.

              // Old ajax style was checking the readystate,
              // newer scripts use the onload event handler. Both can still be found.
              case 'onreadystatechange':
              case 'onload':
                // only create proxy if `value` is a function
                target[property] = 'function' === typeof value
                  ? new Proxy(value, applyEventHandler).bind(receiver)
                  : value
                ;
                break;

              default:
                target[property] = value;

            }
            return true; // success
          }

          catch (e)
          {
            console.error(e);
            return false; // indicate setter error
          }
        }
    },

    oldXMLHttpRequest = window.XMLHttpRequest
  ; // end of local variable declaration

  window.XMLHttpRequest = function(...argv)
  {
    return new Proxy(new oldXMLHttpRequest(...argv), xmlHttpReq_PropertiesHandler);
  }
})();

请注意,此直接访问仅在您不授予任何特权 GM_functions 时才有效。当您被封闭到沙箱中时,您将不得不将函数作为 sting 注入站点的范围,例如 via setTimeout

于 2017-05-11T03:17:29.277 回答