Skip to main content

xhr请求拦截 动态注入

· 3 min read

背景

我们在爬取数据的时候,有些请求的参数是使用各种特殊方式拼接出来的。 这样在我们不了解js中的逻辑下,我们要怎么获取到相关的请求参数呢?

在同一个session下的一些参数一般是固定的,故我们可以从前面的请求中获取请求或者返回参数。然后使用代码模拟请求来进行数据爬去。

获取返回参数

下面有两段代码需要处理。

Ajax-hook代码

// 拦截注入
!function(t){function n(e){if(r[e])return r[e].exports;var i=r[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var r={};return n.m=t,n.c=r,n.p="",n(0)}([function(t,n,r){r(1)(window)},function(t,n){t.exports=function(t){var n="RealXMLHttpRequest";t.hookAjax=function(t){function r(n){return function(){var r=this.hasOwnProperty(n+"_")?this[n+"_"]:this.xhr[n],e=(t[n]||{}).getter;return e&&e(r,this)||r}}function e(n){return function(r){var e=this.xhr,i=this,o=t[n];if("function"==typeof o)e[n]=function(){t[n](i)||r.apply(e,arguments)};else{var u=(o||{}).setter;r=u&&u(r,i)||r;try{e[n]=r}catch(t){this[n+"_"]=r}}}}function i(n){return function(){var r=[].slice.call(arguments);if(!t[n]||!t[n].call(this,r,this.xhr))return this.xhr[n].apply(this.xhr,r)}}return window[n]=window[n]||XMLHttpRequest,XMLHttpRequest=function(){var t=new window[n];for(var o in t){var u="";try{u=typeof t[o]}catch(t){}"function"===u?this[o]=i(o):Object.defineProperty(this,o,{get:r(o),set:e(o),enumerable:!0})}this.xhr=t},window[n]},t.unHookAjax=function(){window[n]&&(XMLHttpRequest=window[n]),window[n]=void 0},t.default=t}}]);

这个是Ajax-hook项目的代码,如果我们使用\<script>的标签来进行注入,有时候回触发网站的安全机制,所以推荐直接从控制台运行整段代码。

请求回调配置

/**
* 打印xhr对象
* @param {*} xhr
*/
function printXhr(xhr) {
console.log("printXhr");
console.log("XMLHttpRequest", xhr);
console.log("XMLHttpRequest.responseText", xhr.responseText);
}

// 设置拦截回调
hookAjax({
open: function(arg, xhr) {
console.log("open", arg);
printXhr(xhr);
},
//拦截回调
onreadystatechange: function(xhr) {
console.log("onreadystatechange called");
printXhr(xhr);
},
onload: function(xhr) {
console.log("onload called");
printXhr(xhr);
}
});
  • open:请求发起的回调,可以在args中获取一些参数。
  • onreadystatechange:返回响应结果时被调用。
  • onload:jQuery是回调的onload(),而不是onreadystatechange()。

所以建议同时拦截onload()和onreadystatechange()来编写逻辑。

拦截请求例子

在selenium中取得数据

  • 查询console打印日志,通过关键字查询出想要的数据。
  • 在回调中增加dom,把相关参数写入,在在selenium获取相关dom的属性。

相关参考

Ajax-hook项目(请求拦截) XMLHttpRequest说明