Greasemonkey:从ajax中获取以供以后使用

时间:2017-05-07 13:48:10

标签: ajax greasemonkey geocaching

网站http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml根据ajax设置的过滤器查看数据。

我可以将这些数据看作条形图。(我登录并验证了身份)

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

我考虑过使用greasemonkey脚本从ajaxcall之后获取响应数据。 也许用" waitForKeyElements"?

有人可以建议解决问题或者给我一个如何解决问题的提示吗?

1 个答案:

答案 0 :(得分: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,此直接访问才有效。当你被封装到沙盒中时,你必须将该函数注入到网站的范围内,例如:通过setTimeout