我想在CasperJS中的函数中执行与Cabybara类似的操作。我想获得父div并从子元素中检索文本。
这样的事情:
$('div.education').find('h4').text()
$('div.education').find('h1').text()
代码段如下:
casper.page.injectJs('/jquery-latest.min.js');
var links = casper.evaluate(function() {
var elements = $('div.education');
return elements.map(function(e){
this.fetchText(casper.evaluate(function(){
return e.find('h4.summary');
}));
this.fetchText(casper.evaluate(function(){
return e.find('h1');
}));
});
});
casper.echo(links);
目前正在返回null
。如何在CasperJS中实现这一目标?
答案 0 :(得分:1)
$('div.education').find('h4')
应该在功能上等同于CSS选择器
'div.education h4'
如果要从这些节点获取文本,可以使用casper.fetchText()
,但它会将所有文本连接成一个字符串。另一个有用的函数是casper.getElementsInfo()
,因为它已经提供了text属性:
casper.then(function(){
var h4Texts = this.getElementsInfo('div.education h4').map(function(h4){
return h4.text;
});
var h1Texts = this.getElementsInfo('div.education h1').map(function(h1){
return h1.text;
});
// do something with h4Texts and h1Texts
});
这个h4和h1文本在同一个父元素的两个不同列表中,可能不是你想要的。你仍然可以使用CasperJS的函数来实现使用CasperJS的XPath支持将h4和h1文本放在一起:
var x = require('casper').selectXPath;
casper.then(function(){
var parents = this.getElementsInfo('div.education');
var result = parents.map(function(divInfo, i){
var h4Texts = this.getElementsInfo(x('(//div[contains(@class,'education')])['+(i+1)+']//h4')
.map(function(h4){
return h4.text;
});
var h1Texts = this.getElementsInfo(x('(//div[contains(@class,'education')])['+(i+1)+']//h1')
.map(function(h1){
return h1.text;
});
return {h1: h1Texts, h4: h4Texts};
});
var h1Texts = this.getElementsInfo('div.education h1').map(function(h1){
return h1.text;
});
// do something with `result`
});
说明
//div[contains(@class,'education')]
返回父元素的节点列表(//div[contains(@class,'education')])['+(i+1)+']
获取i+1
- 父(计数从1开始)和(//div[contains(@class,'education')])['+(i+1)+']//h1
和(//div[contains(@class,'education')])['+(i+1)+']//h4
找到同一父母的h1和h4后代。您的代码存在多个问题。
casper.page.injectJs('/jquery-latest.min.js');
中的文件名应为'./jquery-latest.min.js'
或'jquery-latest.min.js'
jquery与CasperJS脚本位于同一目录中。
然后,似乎你不理解页面上下文和外部casper上下文之间的区别。 casper.evaluate()
函数是沙盒页面上下文。它有一些限制,必须明确地将变量传递给它(完全阅读this),通常this
指的是页面的window
而不是casper
。在你的情况下,你在this
回调中使用map
,它将引用DOM节点的jQuery对象,而不是casper
。此外,jQuery没有.fetchText()
函数,因此会产生错误。页面上下文中也不提供casper
,但您可以使用__utils__
module。
所以你可以像这样编写脚本:
casper.page.injectJs('jquery-latest.min.js');
var links = casper.evaluate(function() {
var elements = $('div.education');
return elements.map(function(){
return {
h4: $(this).find('h4.summary').map(function(){
return $(this).text();
}),
h1: $(this).find('h1').map(function(){
return $(this).text();
})
};
});
});
casper.echo(links);
最后,为了确保您看到所有问题,请注册remote.message
和page.error
事件:
casper.on("remote.message", function(msg){
this.echo("remote.msg: " + msg);
});
casper.on("page.error", function(pageErr){
this.echo("page.err: " + JSON.stringify(pageErr));
});