- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
网页上的数据是动态显示的,似乎检查 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: CasperJS waitForResource: how to get the resource i've waited for):
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 的实现。您需要注入(inject)自己的 onreadystatechange
处理程序实现,收集页面 window
对象中的信息,然后在另一个 evaluate
调用中收集它.
您可能需要查看 XHR faker in sinon.js 或使用以下完整的 XMLHttpRequest
代理(我根据 How can I create a XMLHttpRequest wrapper/proxy? 中的方法 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);
});
或在需要时评估(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 函数来完成的,该函数将接收到的数据写入页面上下文中的 window.myAwesomeResponse
中。您唯一需要做的就是检索此文本。
如果您知道前缀(使用加载的 JSON 调用的函数,例如 insert({"data":["Some", "JSON", "here"] 的话,为 JSONP 编写代理就更容易了,“id”:“asdasda”)
)。您可以在页面上下文中覆盖插入
页面加载后
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();
关于ajax - 如何使用 casperjs 捕获和处理 XHR 响应中的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24555370/
运行测试时获取。 FAIL 35 tests executed in 16.806s, 35 passed, 0 failed, 2 dubious, 0 skipped. “可疑”意味着什么?如何查
是否有人已经使用 casperjs 实现了著名的“页面对象模式”,从长远来看,它对于测试的可维护性非常有用? 当您必须将测试的机制和目的分开时,使用它非常非常酷。以这种方式编写测试会变得更加愉快。 有
所以,我试图在我的服务器上运行 casperJS 作为 cron 作业,这是 crontab: * * * * * /usr/local/bin/casperjs /var/www/javascrip
我知道如何禁用图像和插件,但似乎没有明显的选项来禁用 CasperJS 中的 css。 有谁知道这是如何工作的? 最佳答案 假设您想抑制所有外部样式表的加载,您可以通过中止加载 css 文件的请求来实
我在删除网站时从创建的 URL 下载文件时遇到问题。目前我发现了一个文件的月份和年份,然后替换了 url 中的值并尝试从该位置下载。我了解到您无法使用评估范围内的下载功能。 this.evaluate
在 CasperJS 中,如何在使用 casper.thenOpen() 时保持 session 例如: var casper = require('casper').create(); casper
我希望我的 casper 在 session 期间登录并保持登录状态。有可能吗?如果是这样,如何? 最佳答案 如果你想在 CasperJS 中存储 cookie,你可以使用 PhantomJS coo
我用 casperjs 编写了一些测试。他们与 phantomjs 一起运行得很好。但是,当我尝试通过以下命令使用 slimerjs 时: casperjs --verbose --engine=sl
我用 casperjs 编写了一些测试。他们与 phantomjs 一起运行得很好。但是,当我尝试通过以下命令使用 slimerjs 时: casperjs --verbose --engine=sl
我想单击“提交”按钮,等待下一页加载,然后在第二页上获取html。。我先做然后再运行,但然后一步仍在首页上运行。有任何想法吗? var casper = require('casper').creat
在我的页面自动化脚本中,当我单击标签链接时,将打开一个新窗口。链接的 url 是由复杂的 javascript 生成的。 办理任务 触发后 url 变为: https://oa.phicomm.co
CasperJS(带有 phantomJS)可以直接在浏览器中运行而不是通过命令行运行吗? 我想从浏览器运行交互式测试,我从用户那里获取输入并相应地进行。我想将 casperJS 作为在浏览器中执行的
我正在尝试使用 CasperJS 将图像上传到网络表单。 我的表格看起来像这样: ... Campaign Banner
错误: casper.test property is only available using the `casperjs test` command 在我的整个代码库中搜索了“casper.tes
假设我有一组网址。我不想使用 thenOpen 函数。因为它等待每个以前的 url 被加载并且它减少了加载时间。 casper.each(hrefs,function(self,href){
我正在尝试导航到从脚本本身创建的 url。 此示例代码不像(我曾)预期的那样工作。不知道为什么:( var casper = require('casper').create({ viewpo
我有一个链接列表,我必须模拟这些链接才能使用CasperJS进行点击。他们都共享同一个类(class)。 但是,使用this.click('.click-me')仅单击第一个链接。 单击所有链接的正确
casper.then(function(){ phone_number = '7wqeqwe6'; phone_password = 'Teqweqweqw34'; }); casper.t
我如何告诉 casper 不要加载图像、css、js 视频等。所以我只对 DOM 元素感兴趣。 最佳答案 看看 CasperJS API . var casper = require('casper'
在Phantom中生成PDF时,我可以这样设置纸张大小: page.paperSize = { height: '8.5in', width: '11in', orientation: '
我是一名优秀的程序员,十分优秀!