等到下拉列表元素在 CasperJS 中可见

Wait until drop-down list element is visible in CasperJS

我有这个下拉列表:

<select name="date" class="form-control" on-change:Calendar.submitFilterForm();">
    <option value="2015-09-15">Tue 2015-09-15</option>
    <option value="2015-09-16">Wed 2015-09-16</option>
    <option value="2015-09-17">Thu 2015-09-17</option> 
    <option value="2015-09-18">Fri 2015-09-18</option>
    <option value="2015-09-19">Sat 2015-09-19</option>
    <option value="2015-09-20">Sun 2015-09-20</option>
    <option value="2015-09-21">Mon 2015-09-21</option>
    <option value="2015-09-22">Tue 2015-09-22</option>
</select>

每天晚上 00:00 上午(或几秒钟后),上面的下拉列表会更新为新的(下)一天,例如 <option value="2015-09-23">Wed 2015-09-23</option> 将被添加并且 <option value="2015-09-15">Tue 2015-09-15</option> 会消失。

然后我想点击那个一出现就添加的下拉列表选项。可能吗?

现在我使用:

casper.thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

有效,但我应该如何处理 make casperjs wait until the options is visible and then directly click on it? 也许我可以创建一个变量 var ClickValue = "2015-09-23" 或类似的东西?

CasperJS 不适合安排长 运行ning 任务,因为底层浏览器(PhantomJS 或 Slimer.js)可能 运行 进入内存问题或以其他方式失败。因此,您应该编写一个简短的 运行ning 脚本,该脚本只等待很短的时间直到元素出现。您可以通过操作系统安排在午夜之前执行此脚本(cron Linux 或 Windows)。

元素出现在 JavaScript

如果 select 字段由 JavaScript 更新,那么您可以简单地使用 "long"-运行ning waitFor():

casper.then(function(){
    var lastDate = this.getElementAttribute(".form-control :last-child", "value");
    this.waitFor(function(){
        return this.getElementAttribute(".form-control :last-child", "value") !== lastDate;
    }, null, null, 600000); // 10 minutes
}).thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

需要重新加载页面

如果您只有在重新加载页面时才会看到添加的选项,那么每次检查都需要casper.reload()该页面。

casper.then(function(){
    var lastDate = this.getElementAttribute(".form-control :last-child", "value");

    function checkReload(){
        var curDate = this.getElementAttribute(".form-control :last-child", "value");
        if (lastDate !== curDate) { // TODO: add timeout handling here
            return; // finished
        }

        this.reload();
        this.wait(1000, checkReload); // check again in a second
    }
    this.then(checkReload);
}).thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

这 运行 是无限期的,因此您应该添加超时处理。

无需与预先计算的日期进行比较

上述解决方案通过将先前的选项值与当前值进行比较来工作。这并不完全可靠,因为如果出现错误并且脚本在新选项出现时启动,那么脚本将 运行 再过 24 小时。您还可以将其更改为通过创建预期的

直接计算预期的期权价值
var d = new Date(Date.now()+(1000 * 60 * 60 * 24 * 7)); // seven days later
var expectedValue = ""+d.getFullYear()
        +"-"+zeroFill(d.getMonth()+1, 2)
        +"-"+zeroFill(d.getDate(), 2);

expectedValue 将替换前面代码段中的 lastDate,并且不要忘记将比较从 !== 翻转为 ===
zeroFill() 取自 here.