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

Loop over an array to try multiple options on a page and come back to that initial page for each iteration

我正在使用 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() 报告每次通过循环时数组中第一个状态的结果。对于第 2 步,我尝试了多种不同的方法(来自 SO 上的帖子),但无济于事。

如何让循环等到步骤 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.evaluatethis.waitForSelector 函数不是 "finding" 浏览器上下文中的正确页面。我希望输出看起来像:

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

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

单击提交按钮会导航到另一个页面,但问题似乎是您不再位于 eachThen 的下一次迭代的初始页面上:

So each pass through this.each should navigate back to the first page after step 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 不会在一个步骤中转到预重定向页面.


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

你看到一个不同的短状态名称,但总是相同的长状态名称的原因是因为 states 在你开始迭代之前就已填充,但在第一次迭代后你继续在同一页面上.

您可能早先通过收听 "page.error" event 发现您的脚本存在问题,该 "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);