如何在 CasperJS 中对多个页面进行嵌套循环

How to do nested looping over many pages in CasperJS

我不知道从哪里开始。基本上我需要 CasperJS 运行 通过大约 15 个不同的页面,它 运行 通过它的每个页面都需要获取 150 个需要设置为 cookie 值的不同位置的数据。对于每个位置,我需要检查 5 个不同日期的数据。

这些中的任何一个看起来都很简单,但试图让所有三个都发生却让我感到困惑。

我试过这样设置:

for(Iterate through URLs){
  for(Iterate through locations){
    for(Iterate through dates){
      phantom.addCookie({
        // Cookie data here based on location and date
      });
      casper.start(url)
      .then(function(){
        // Do some stuff here
      })
      .run();
    }
  }
}

基本上它所做的是遍历所有内容,然后根据最后 link、最后位置、最后日期加载页面。但是其他所有位置都会被跳过。有没有更简单的方法来做到这一点?也许更好,有没有办法告诉我的 JavaScript 循环在跳转到下一个循环迭代之前等待 casper 完成它需要做的事情?

如果需要,我很乐意提供更多详细信息。我尽量简化了流程,但没有删掉所需的信息。

差不多就这些了。需要注意两件事:

  • casper.start()casper.run() 每个脚本只能调用一次。您可以使用 casper.thenOpen() 打开不同的 URL。

  • 请记住,所有 casper.then*()casper.wait*() 函数都是异步步骤函数,仅安排在当前步骤之后执行。由于 JavaScript 具有函数级别范围,因此您需要 "fix" 每次迭代的迭代变量,否则您将仅获得最后一次 URL。 (More information)

示例代码:

casper.start(); // deliberately empty

for (var url in urls) {
    for (var location in locations) {
        for (var date in dates) {
            (function(url, location, date){
                casper.then(function(){
                    phantom.addCookie({
                        // Cookie data here based on location and date
                    });
                }).thenOpen(url)
                    .then(function(){
                        // Do some stuff here
                    });
            })(url, location, date);
        }
    }
}

casper.run(); // start all the scheduled steps

如果您使用 Array.prototype.forEach 而不是 for 循环,那么您可以安全地跳过使用 IIFE 来修复变量。

我不确定,但您可能需要先打开一个页面,然后为该域添加 cookie。 PhantomJS 可能只在该 cookie 的域当前打开时才接受该 cookie。