- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在遇到麻烦后(第一个计时器 nodejs 和 casperjs/phantomjs),它开始工作了。我用 curl(php) 完成了这项工作。
这是我试图完成的:
casper.start(url, function() {
this.evaluate(function() {
document.querySelector("input[name='username']").value = "username";
document.querySelector("input[name='password']").value = "passwrd";
document.querySelector("#login").click();
});
console.log("Logged in..");
});
var processPage = function() {
console.log("Get all units..");
var units = this.evaluate(getUnits);
allUnits.push(units);
if (!this.evaluate(isLastPage)) {
this.thenClick('.paging li:last-child a').then(function() {
currentPage++;
console.log("Stepping to page.. " + currentPage);
this.waitFor(function() {
return currentPage === this.evaluate(getSelectedPage);
}, processPage, terminate);
});
} else{
require('utils').dump(allUnits);
casper.then(function() {
this.capture('test.png');
});
console.log("Total unit count: " + allUnits.length);
}
};
casper.waitForSelector('.units', processPage, terminate);
casper.run();
在下面的函数中,我解析了行,我也想添加 ajax 获取的 2 个详细信息,但我不知道该怎么做。 (异步)
function getUnits() {
var rows = document.querySelectorAll('.units');
var units = [];
for (var i = 0, row; row = rows[i]; i++) {
var aID = row.querySelector('a').getAttribute('href').split('/');
unit['id'] = aID[2];
//add other details for the unit
**//Do a async call to the 2 external links with the ID and add the details to the unit**
units.push(unit);
}
return units;
};
需要注意的是,最后我想在单元上运行另一个函数,但在运行它之前必须已经获取所有函数......
编辑
登录后页面显示一个表格,我得到的是这样的表格
我试图用 casper 正常获取最后 2 个字段,但有时它得到了值,有时却没有(请求有时太慢)
我想知道的是如何在不等待每一行(单位)直到它获得值的情况下获得这些字段。 (所以每个单元都应该为他们自己获取值并将它们填充到他们的对象中。所以可能需要回调?
或者我可以自己完成请求,我只需要 ID 和 cookie 来发帖(链接将 ID 和 Cookie 作为参数)并获取详细信息并填写,但我不知道该怎么做或者如果第一个解决方案效果更好,或者即使这是可能的......
最重要的是,在所有单元都有它们的详细信息之后,它应该继续应用程序的逻辑...
最佳答案
由于 PhantomJS(和 CasperJS)有两个上下文,因此很容易脱离执行流程。
我看到有两种方法可以解决您的问题。
您需要在页面上下文内部(evaluate()
内部)触发请求,并让外部上下文等待结果。我假设您可以在页面上下文中进行成功回调。
您必须将外部请求的结果放在全局某个地方,以便外部上下文可以访问它。例如,像这样修改您的 getUnits()
函数:
function getUnits() {
var rows = document.querySelectorAll('.units');
var units = [];
window.__externalRequestResults = [[], []];
for (var i = 0, row; row = rows[i]; i++) {
var aID = row.querySelector('a').getAttribute('href').split('/');
unit['id'] = aID[2];
//add other details for the unit
//Do a async call to the 2 external links with the ID and add the details to the unit
(function(i){
var xhr = new XMLHttpRequest();
xhr.open("GET", someURLwithParameters, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4) { // DONE
__externalRequestResults[0][i] = xhr.responseText;
}
};
xhr = new XMLHttpRequest();
xhr.open("GET", someOtherURLwithParameters, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4) { // DONE
__externalRequestResults[1][i] = xhr.responseText;
}
};
xhr.send();
})(i);
units.push(unit);
}
return units;
};
现在您可以检索即时结果,然后等待其他结果:
var processPage = function() {
console.log("Get all units..");
var units = this.evaluate(getUnits);
var numberOfRows = this.getElementsInfo("table tr").length; // TODO: fix selector
var externalUnits;
this.waitFor(function test(){
externalUnits = this.getGlobal("__externalRequestResults");
for(var i = 0; i < numberOfRows; i++) {
if (externalUnits[0][i] == null || externalUnits[1][i] == null) {
return false
}
}
return true;
}, function _then(){
allUnits.push(units);
allUnits.push(externalUnits); // TODO: maybe a little differently
if (!this.evaluate(isLastPage)) {
//... as before
} else{
//... as before
}
}, terminate);
};
当两个附加数据列表的数量与表的行数相同且所有行都已填充时,触发等待期结束。这会创建一个稀疏数组,并且 Array#push()
无法使用,因为不同的 Ajax 请求可能会以与发送它们时不同的顺序出现。
在第二种情况下,您让 CasperJS 等待所有数据进入。挑战在于编写一个执行此操作的检查函数。
var processPage = function() {
console.log("Get all units..");
var numberOfRows = this.getElementsInfo("table tr").length; // TODO: fix selector
this.waitFor(function test(){
var data1, data2;
for(var i = 1; i <= numberOfRows; i++) {
data1 = this.fetchText("table tr:nth-child("+i+") td:nth-child(4)") || "";
data2 = this.fetchText("table tr:nth-child("+i+") td:nth-child(5)") || "";
if (data1.trim() === "" || data2.trim() === "") {
return false
}
}
return true;
}, function _then(){
var units = this.evaluate(getUnits);
allUnits.push(units);
if (!this.evaluate(isLastPage)) {
//... as before
} else{
//... as before
}
}, terminate);
};
现在,您甚至不需要在 getUnits()
中发出 Ajax 请求,只需收集所有静态信息即可。
不要忘记将失败的等待超时设置得足够大,以便所有 Ajax 请求都能及时完成。例如,比所有 ajax 请求加载的正常时间大 3 或 4 倍。您可以使用全局 casper.options.waitTimeout
为此。
关于javascript - 同步 CasperJS 操作期间的异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31484329/
运行测试时获取。 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: '
我是一名优秀的程序员,十分优秀!