循环遍历数组以尝试页面上的多个选项,并在每次迭代时返回到该初始页面

时间:2015-11-20 23:08:39

标签: javascript phantomjs casperjs

我正在使用CasperJS从网站上抓取一些数据。在主页面上,有一个下拉列表,其中包含所有50个州的列表。该值是2个字母的缩写。

var states;
casper.start(url);
casper.then(function() {
    states = this.evaluate(function getOptionVals() {
        // loop thru and get the values
        return arrayValues;
    });
});

接下来我想循环通过缩写数组,然后在同一页面上填充一些元素。该页面上没有表格,只有一些单选按钮和一个提交按钮。

提交按钮导航到新的.asp页面,将搜索选项作为查询字符串参数传递。

casper.then(function () {
    // loop over all states
    this.eachThen(states,function(state) {
        this.echo('state = ' + state.data);
        // step 1
        this.evaluate(function(state) {
            console.log('In .evaluate the state is '+state);
            // select the radio button
            $('#searchoption1').prop('checked',true);
            $('#searchoption2').prop('checked',false);
            $('#showall').prop('checked',true);
            // select the State from the dropdown
            $('#state option[value="'+state+'"]').prop('selected', true);
            $('#submit1').click();
        },state.data); // pass in the array from the first casper.then call
        // step 2
        this.waitForSelector('table.mainTable tbody table  tbody blockquote',function() {
            this.evaluate(function(){
                console.log($('table.mainTable h1 ').text());
            });
        });
    })
});
casper.run();

我的问题是CasperJS的异步性质。当我运行它时,console.log()报告每次通过循环时数组中第一个状态的结果。我已经尝试了一系列不同的方法(来自SO上的帖子)第2步,但无济于事。

如何让循环等到第2步完成后再继续?

以下是输出结果:

start step #1 get state abbreviations
start #2 loop over all states
state = AL
In .evaluate the state is AL
loc: (/Find_Range/wts_subresults_test.asp)
dir2: (e)
Ranges for the State/Province of Alabama
state = AK
In .evaluate the state is AK
Ranges for the State/Province of Alabama
state = AZ
In .evaluate the state is AZ
Ranges for the State/Province of Alabama
state = AR
In .evaluate the state is AR
Ranges for the State/Province of Alabama
state = CA
In .evaluate the state is CA
Ranges for the State/Province of Alabama
state = CO
In .evaluate the state is CO
Ranges for the State/Province of Alabama
state = CT
In .evaluate the state is CT
Ranges for the State/Province of Alabama

因此this.waitForSelector this.evaluate函数与In .evaluate the state is AL loc: (/Find_Range/wts_subresults_test.asp) dir2: (e) Ranges for the State/Province of Alabama state = AK In .evaluate the state is AK Ranges for the State/Province of Alaska state = AZ In .evaluate the state is AZ Ranges for the State/Province of Arizona state = AR In .evaluate the state is AR Ranges for the State/Province of Arkansas state = CA In .evaluate the state is CA Ranges for the State/Province of California state = CO In .evaluate the state is CO Ranges for the State/Province of colorado 无法在浏览器上下文中“找到”正确的页面。我希望输出看起来像:

{{1}}

所以每次通过this.each都应该在第2步之后导航回第一页。

1 个答案:

答案 0 :(得分:2)

点击提交按钮导航到另一个页面,但问题似乎是您不再在eachThen的下一次迭代中进入初始页面了:

  

所以每次通过this.each都应该在第2步之后导航回第一页。

此时您有两种选择:

1。在每次迭代中打开您在开始时所在的页面:

casper.then(function () {
    var url = this.getCurrentUrl();
    // loop over all states
    this.eachThen(states, function(state) {
        this.echo('state = ' + state.data);
        // step 0
        this.thenOpen(url);
        // step 1
        this.thenEvaluate(...);
        // step 2
        this.waitForSelector(...);
    })
});

请注意,我使用了thenEvaluate而不是evaluate,因为像evaluate这样的同步函数调用不应该像thenOpen这样的异步步调用函数调用。

2。回去:

casper.then(function () {
    // loop over all states
    this.eachThen(states, function(state) {
        this.echo('state = ' + state.data);
        // step 1
        this.thenEvaluate(...);
        // step 2
        this.waitForSelector(...);
        // step 3
        this.back();
    })
});

请注意,您可能必须使用back两次(或更多):this.back().back();,因为有时候会有重定向,而PhantomJS不会一步到达预重定向页面。< / p>

如果您使用CasperJS进行导航,那么通常只有一个page实例。单击某些内容并创建新窗口/弹出窗口时,可以创建其他页面实例,但这不是这里发生的事情。

您看到不同的短状态名称但始终具有相同的长状态名称的原因是因为在您开始迭代之前填充了states,但是在第一次迭代之后您仍然在同一页面上。 / p>

您之前可能已经注意到您的脚本存在问题,因为它会向您显示无法找到某些元素的"page.error" event(在第一次迭代后的evaluate内):

casper.on("page.error", function(msg, trace) {
    this.echo("Error: " + msg);
    // maybe make it a little fancier with the code from the PhantomJS equivalent
});

此外,如果您想知道发生了什么,您应该在每个有趣的屏幕截图casper.capture(filename);