Javascript CasperJS,多元素在刮取过程中单击
我正在尝试刮取一个页面,并将所有数据作为JSON返回。这个过程是,我首先打开www.domain.com,将各种信息放入节点数组,但对于每个节点,还有另一个页面,我想从中提取额外的数据并存储在节点数组中。我需要在循环中执行此操作,或者至少能够传递x变量,以便知道将此数据推送到数组中的位置 我已经把这段代码剥离了回来,还没有检查它是否正常工作,但是我的主版本工作得很好 非常感谢您的帮助…谢谢Javascript CasperJS,多元素在刮取过程中单击,javascript,phantomjs,casperjs,Javascript,Phantomjs,Casperjs,我正在尝试刮取一个页面,并将所有数据作为JSON返回。这个过程是,我首先打开www.domain.com,将各种信息放入节点数组,但对于每个节点,还有另一个页面,我想从中提取额外的数据并存储在节点数组中。我需要在循环中执行此操作,或者至少能够传递x变量,以便知道将此数据推送到数组中的位置 我已经把这段代码剥离了回来,还没有检查它是否正常工作,但是我的主版本工作得很好 非常感谢您的帮助…谢谢 var nodes = {}; var casper = require('casper').creat
var nodes = {};
var casper = require('casper').create({
pageSettings: {
loadImages: false,
},
verbose: true
});
var url = "http://www.domain.com";
function get_rows()
{
var nodes = {};
var el = document.querySelectorAll(".rows");
nodes["rows"] = {};
for(var x = 0; x < el.length; ++x)
{
// Set the arrays
nodes["rows"][x] = {};
nodes["rows"][x] = el[x].innerHTML;
// THIS DATA IS ON A SEPARATE PAGE
// el[x].click IS HOW YOU'D VISIT THAT PAGE
nodes["rows"][x]["data"] = {};
}
return nodes;
}
function get_data()
{
casper.echo("get_data");
rows = casper.evaluate(get_rows);
casper.echo(JSON.stringify(rows));
}
casper.start(url, function()
{
this.echo('Starting...' + this.getTitle());
});
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0');
casper.viewport(320, 480);
casper.waitFor
(
function check()
{
return this.evaluate(function()
{
return $('.content').is(':visible');
});
},
function then()
{
this.capture("/work/screen.png");
// Lets go get the data
this.echo("About to get_data()");
get_data();
},
function timeout()
{
// step to execute if check has failed
this.echo("Timeout: page did not load in time...").exit();
}
);
casper.run();
您必须将get_rows函数拆分为多个函数。第一个将检索.rows元素的数量。casper.getElementsInfo为每个匹配的元素提供一个html属性,可在页面上下文之外调用
var nodes;
var x = require('casper').selectXPath;
casper.then(function(){
nodes = {
rows: {}
};
var elements = this.getElementsInfo(".rows");
for(var i = 0; i < elements.length; i++) {
nodes.rows[i] = {
html: elements[i].html
};
(function(i){
// TODO: click on the correct link
casper.thenClick(x("(//*[contains(@class,'rows')])["+(i+1)+"]//a"));
casper.then(function(){
nodes.rows[i].data = this.evaluate(function(){
return { stuff: "whatever" }; // scrape here
});
});
casper.back(); // assumes this works for your page
})(i);
}
}).then(function(){
this.echo(JSON.stringify(nodes.rows, undefined, 4));
});
生命函数i{…}i;重要的是,否则只会填充最后一个i。这是因为JavaScript具有函数级作用域,而CasperJS的then*函数是异步的
如果casper.back对您不起作用,您需要使用casper.back重新加载主页面,然后打开。这就是我目前所处的位置……第一次求值返回一个对象,效果非常好,但在每个装置中,我希望获得另一页数据,要单击的元素只是一个名为.Fixture的重复类,因此我使用第n个子元素尝试并以相关元素为目标。代码从未真正创建捕获
fixtures = casper.evaluate(get_fixtures);
casper.echo("Fixtures: "+Object.keys(fixtures).length );
casper.then(function()
{
Object.keys(fixtures).forEach(function(key)
{
casper.echo(fixtures[key]["competition"]);
(function(key)
{
casper.echo(".Fixture:nth-child("+key+")");
var pageturnString = key.toString();
var linknum = 'div.Fixture:nth-child('+pageturnString+')';
casper.thenClick(linknum);
casper.then(function()
{
casper.capture('/work/screen_click.png');
});
casper.back(); // assumes this works for your page
})(key);
});
}).then(function()
{
casper.echo("END");
});
我不确定这是否可以作为get_rows函数使用,因为这是在CasperJS不在范围内的求值调用中调用的?这就是为什么您必须将其拆分为多个步骤,并且大多数步骤都必须在页面上下文之外执行的原因。感谢Artjom,我将尝试一下,看看givesIt没有真正执行什么,没有进一步的转发,但我非常感谢您的回复。您可能很难找到正确的链接来点击。我在一个小助手的帮助下改变了答案。如果你想放弃,问一个新的问题。