网页上的数据是动态显示的,似乎检查html中的每个更改并提取数据是一项非常艰巨的任务,并且还需要我使用非常不可靠的XPath。因此,我希望能够从XHR
数据包中提取数据。
我希望能够从XHR
数据包中提取信息以及生成要发送到服务器的“
XHR”数据包。提取信息部分对我来说更重要,因为通过使用casperjs自动触发html元素可以轻松处理信息的发送。
我附上我的意思的屏幕截图。
响应选项卡中的文本是我以后需要处理的数据。(已从服务器收到此XHR响应。)
这是不容易的,因为该resource.received
事件处理程序只提供元数据一样url
,headers
或者status
,但不是实际的数据。底层phantomjs事件处理程序的行为方式相同。
如果ajax调用 是无状态的 ,则可以重复该请求
casper.on("resource.received", function(resource){
// somehow identify this request, here: if it contains ".json"
// it also also only does something when the stage is "end" otherwise this would be executed two times
if (resource.url.indexOf(".json") != -1 && resource.stage == "end") {
var data = casper.evaluate(function(url){
// synchronous GET request
return __utils__.sendAJAX(url, "GET");
}, resource.url);
// do something with data, you might need to JSON.parse(data)
}
});
casper.start(url); // your script
您可能需要将事件侦听器添加到中resource.requested
。这样,您就无需完成呼叫。
您也可以像这样在控制流中执行此操作源:A:CasperJSwaitForResource:如何获取我等待的资源:
casper.start(url);
var res, resData;
casper.waitForResource(function check(resource){
res = resource;
return resource.url.indexOf(".json") != -1;
}, function then(){
resData = casper.evaluate(function(url){
// synchronous GET request
return __utils__.sendAJAX(url, "GET");
}, res.url);
// do something with the data here or in a later step
});
casper.run();
如果 不是无状态的
,则需要替换XMLHttpRequest的实现。您将需要注入自己的onreadystatechange
处理程序实现,在page
window
对象中收集信息,然后在另一个evaluate
调用中收集它。
您可能想要查看sinon.js中的XHR伪造者,或使用以下完整代理XMLHttpRequest
(我如何创建XMLHttpRequest包装器/代理中的方法3建模):
function replaceXHR(){
(function(window, debug){
function args(a){
var s = "";
for(var i = 0; i < a.length; i++) {
s += "\t\n[" + i + "] => " + a[i];
}
return s;
}
var _XMLHttpRequest = window.XMLHttpRequest;
window.XMLHttpRequest = function() {
this.xhr = new _XMLHttpRequest();
}
// proxy ALL methods/properties
var methods = [
"open",
"abort",
"setRequestHeader",
"send",
"addEventListener",
"removeEventListener",
"getResponseHeader",
"getAllResponseHeaders",
"dispatchEvent",
"overrideMimeType"
];
methods.forEach(function(method){
window.XMLHttpRequest.prototype[method] = function() {
if (debug) console.log("ARGUMENTS", method, args(arguments));
if (method == "open") {
this._url = arguments[1];
}
return this.xhr[method].apply(this.xhr, arguments);
}
});
// proxy change event handler
Object.defineProperty(window.XMLHttpRequest.prototype, "onreadystatechange", {
get: function(){
// this will probably never called
return this.xhr.onreadystatechange;
},
set: function(onreadystatechange){
var that = this.xhr;
var realThis = this;
that.onreadystatechange = function(){
// request is fully loaded
if (that.readyState == 4) {
if (debug) console.log("RESPONSE RECEIVED:", typeof that.responseText == "string" ? that.responseText.length : "none");
// there is a response and filter execution based on url
if (that.responseText && realThis._url.indexOf("whatever") != -1) {
window.myAwesomeResponse = that.responseText;
}
}
onreadystatechange.call(that);
};
}
});
var otherscalars = [
"onabort",
"onerror",
"onload",
"onloadstart",
"onloadend",
"onprogress",
"readyState",
"responseText",
"responseType",
"responseXML",
"status",
"statusText",
"upload",
"withCredentials",
"DONE",
"UNSENT",
"HEADERS_RECEIVED",
"LOADING",
"OPENED"
];
otherscalars.forEach(function(scalar){
Object.defineProperty(window.XMLHttpRequest.prototype, scalar, {
get: function(){
return this.xhr[scalar];
},
set: function(obj){
this.xhr[scalar] = obj;
}
});
});
})(window, false);
}
如果您想一开始就捕获AJAX调用,则需要将其添加到第一个事件处理程序中
casper.on("page.initialized", function(resource){
this.evaluate(replaceXHR);
});
或evaluate(replaceXHR)
在需要时使用。
控制流如下所示:
function replaceXHR(){ /* from above*/ }
casper.start(yourUrl, function(){
this.evaluate(replaceXHR);
});
function getAwesomeResponse(){
return this.evaluate(function(){
return window.myAwesomeResponse;
});
}
// stops waiting if window.myAwesomeResponse is something that evaluates to true
casper.waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
});
casper.run();
如上所述,我为XMLHttpRequest创建了一个代理,以便每次在页面上使用它时,我都可以对其进行处理。您抓取的页面使用xhr.onreadystatechange
回调来接收数据。通过定义一个特定的setter函数来完成代理,该setter函数将接收到的数据写入window.myAwesomeResponse
页面上下文中。您唯一需要做的就是检索此文本。
如果您知道前缀(使用加载的JSON调用的函数,例如insert({"data":["Some", "JSON", "here"],"id":"asdasda")
),则为JSONP编写代理甚至更加容易。您可以insert
在页面上下文中覆盖
页面加载后
casper.start(url).then(function(){
this.evaluate(function(){
var oldInsert = insert;
insert = function(json){
window.myAwesomeResponse = json;
oldInsert.apply(window, arguments);
};
});
}).waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
}).run();
或在接收到请求之前(如果在调用请求之前就注册了该函数)
casper.on("resource.requested", function(resource){
// filter on the correct call
if (resource.url.indexOf(".jsonp") != -1) {
this.evaluate(function(){
var oldInsert = insert;
insert = function(json){
window.myAwesomeResponse = json;
oldInsert.apply(window, arguments);
};
});
}
}).run();
casper.start(url).waitFor(getAwesomeResponse, function then(){
var data = JSON.parse(getAwesomeResponse());
// Do something with data
}).run();
问题内容: 我单击Firefox中的链接,网页使用javascript发送请求,然后服务器发送某种响应,其中包括网站地址。这样,新网站就会在新窗口中打开。链接后面的html代码是(我省略了initial和final 标签): 我想捕获服务器响应并使用Python和Selenium提取“新网站”。我一直在使用BeautifulSoup进行抓取,对Selenium来说还很陌生。 到目前为止,我已经能够
问题内容: 我有以下代码: 我想捕获HTML响应?我该怎么做呢?我可以向form1.submit方法注册任何回调函数吗? 问题答案: 使用普通的javascript,您将无法轻松做到这一点。发布表单时,表单输入将发送到服务器,页面会刷新- 数据在服务器端处理。也就是说,该函数实际上不返回任何东西,它只是将表单数据发送到服务器。 如果您真的想用Javascript获得响应(无需刷新页面),则需要使用
我注意到我的不能处理Spring Security在Spring Boot应用程序中引发的异常。 但是,我需要一种方法来捕获,当用户帐户仍然被禁用时,它似乎会被抛出。 用例很简单:如果一个用户当前被禁用,我想抛出一个适当的错误给我的客户机S.T。它可以相应地显示一条消息。 现在Spring Security的回应是 我看到了这个问题,但由于某种原因,我的没有被调用: 知道我错过了什么吗? 这是我的
我试图拦截来自所有promise然后方法的响应。但是我不能在原型然后方法中得到响应数据。请找到下面的代码。 在上面的代码中,我可以看到控制台打印在所有Promise调用中。但是我无法在then中获得响应对象。 控制台中打印的this对象值: “then”原型方法中的打印参数: 请建议我在then方法中获取所有promise方法的响应对象。 我尝试使用“arguments[0].arguments”
根据节点获取文档节点获取 我们可以这样得到响应状态 为了得到数据 我有一个场景,需要从响应返回JSON数据和状态。我试着这样用 但是 安慰日志(jsonData.status) 不会返回状态。如何获取状态和输出数据
考虑下面的代码: 我想做的是用我应该从JSON响应中获得的错误消息捕获错误。我希望在我的第二个console.log中得到一个响应,但是不知何故,响应在第一个console.log.我如何在第一个实例中得到我想要的响应? 此外,为什么响应在第一个实例中给我“ok”,即使应用编程接口密钥不存在? 为什么我必须返回rsp.json()才能在第二个实例中获得正确的JSON,而响应应该已经是JSON格式的