【问题标题】:Loop over an array to try multiple options on a page and come back to that initial page for each iteration循环遍历数组以尝试页面上的多个选项,并为每次迭代返回初始页面
【发布时间】:2015-11-21 19:28:53
【问题描述】:

我正在使用 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.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

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

【问题讨论】:

    标签: javascript phantomjs casperjs


    【解决方案1】:

    单击提交按钮导航到另一个页面,但问题似乎是您不在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 不会一步进入重定向前页面。


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

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

    您可能早先通过收听"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);

    【讨论】:

    • 这正是我想要的!现在我看到了我第一次不使用 thenEvaluate 所犯的错误。 (我在 waitForSelector 回调中尝试过。)我也尝试过使用 page.error 事件,但是页面上有很多 js 错误,他们只是混淆了这个问题。 (我不控制我正在抓取的页面)。使用 this.capture 也是一个不错的建议。显然,我是 capturejs 的新手,我很感谢您的建议。谢谢 Artjom。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    相关资源
    最近更新 更多