javascript - 使用 CasperJS 计算失败的 DOM 元素

标签 javascript css-selectors casperjs

我刚刚遇到 CasperJS 的问题。

我需要计算表行数,因为有很多表包含相同的信息结构(比方说用户表) 所以我做了一些像这样的 casperjs 评估代码

var table_rows1 = casper.evaluate(function(it){ return jQuery("#dResult > div:nth-child("+1+") > div > div:nth-child(4) > div:nth-child("+it+") > div:nth-child(1) > span > div").length; }, it);

它是迭代器,它会递增直到达到表元素长度。

假设我们有 3 个表,那么它将是 1,2,3 对于它 = 1,没有问题发生,它打印出正确的 table[1] 行数。 但是对于下一个 2,3,它只打印 1 作为表格行数。 怎么会变得这么奇怪?

这是我的 CasperJS 片段:

function getNumber(it){
     window.__utils__.echo("it :"+it);
     var query = "#dResult > div:nth-child("+1+") > div > div:nth-child(4) > div:nth-child("+it+") > div:nth-child(1) > span > div";
     return jQuery(query).length;
}
var table_rows1 = casper.evaluate(getNumber, 1);
var table_rows2 = casper.evaluate(getNumber, 2);
var table_rows3 = casper.evaluate(getNumber, 3);

this.echo("table rows #1 :"+table_rows1);
this.echo("table rows #2 :"+table_rows2);
this.echo("table rows #3 :"+table_rows3);

这是我需要抓取的 html...

这是1个表格,有很多这样的html标签

<div class="padd-b-rates">
        <div id="showRateWSMA0511000015CL096-CL124">
            <div class="bd-rate-in">
                <div class="rth1"><b>Room Category </b></div>
                <div class="rth2"><b>Breakfast</b></div>
                <div class="rth3"><b>Total Stay</b></div>
                <div class="rth4"><b>Room Status</b></div>
                <div class="clear"></div>
            </div>
            <span id="RateWSMA0511000015CL096-CL124">
    <div class="bd-rate-row">
        <div class="rtd1"><span class="rmname-rsht-rate">DELUXE (NRF)</span><i></i></div>
        <div class="rtd2"><span>Breakfast</span><i></i></div>
        <div class="rtd3"><span><a href="javascript:sHC.ShowPrice('WSMA0511000015','WSMA140400017', 'BB','CL096-CL124');">2,174,005.00 IDR</a></span><i></i></div>
        <div class="rtd4"><span class="btn-rsht-rate" onclick="sHC.jumpToPaxdetail(this);" hotelcode="WSMA0511000015" suppliercode="CL096-CL124" droomcatg="WSMA140400017-BB" roomstatus="Y" id="bookWSMA0511000015WSMA140400017-BB-CL096-CL124"><img border="0" src="/b2b/images/result-hotels/btnAV-v3.gif"></span></div>
        <div class="clear"></div>
    </div>

    <div class="bd-rate-row">
        <div class="rtd1"><span class="rmname-rsht-rate">EXECUTIVE (NRF)</span><i></i></div>
        <div class="rtd2"><span>Breakfast</span><i></i></div>
        <div class="rtd3"><span><a href="javascript:sHC.ShowPrice('WSMA0511000015','WSMA140400018', 'BB','CL096-CL124');">2,505,557.00 IDR</a></span><i></i></div>
        <div class="rtd4"><span class="btn-rsht-rate" onclick="sHC.jumpToPaxdetail(this);" hotelcode="WSMA0511000015" suppliercode="CL096-CL124" droomcatg="WSMA140400018-BB" roomstatus="Y" id="bookWSMA0511000015WSMA140400018-BB-CL096-CL124"><img border="0" src="/b2b/images/result-hotels/btnAV-v3.gif"></span></div>
        <div class="clear"></div>
    </div>

    <div class="bd-rate-row">
        <div class="rtd1"><span class="rmname-rsht-rate">DELUXE</span><i></i></div>
        <div class="rtd2"><span>Room Only</span><i></i></div>
        <div class="rtd3"><span><a href="javascript:sHC.ShowPrice('WSMA0511000015','WSMA05110034', 'RO','CL096-CL124');">2,743,860.00 IDR</a></span><i></i></div>
        <div class="rtd4"><span class="btn-rsht-rate" onclick="sHC.jumpToPaxdetail(this);" hotelcode="WSMA0511000015" suppliercode="CL096-CL124" droomcatg="WSMA05110034-RO" roomstatus="Y" id="bookWSMA0511000015WSMA05110034-RO-CL096-CL124"><img border="0" src="/b2b/images/result-hotels/btnAV-v3.gif"></span></div>
        <div class="clear"></div>
    </div>

    <div class="bd-rate-row">
        <div class="rtd1"><span class="rmname-rsht-rate">DELUXE</span><i></i></div>
        <div class="rtd2"><span>Breakfast</span><i></i></div>
        <div class="rtd3"><span><a href="javascript:sHC.ShowPrice('WSMA0511000015','WSMA05110034', 'BB','CL096-CL124');">2,847,470.00 IDR</a></span><i></i></div>
        <div class="rtd4"><span class="btn-rsht-rate" onclick="sHC.jumpToPaxdetail(this);" hotelcode="WSMA0511000015" suppliercode="CL096-CL124" droomcatg="WSMA05110034-BB" roomstatus="Y" id="bookWSMA0511000015WSMA05110034-BB-CL096-CL124"><img border="0" src="/b2b/images/result-hotels/btnAV-v3.gif"></span></div>
        <div class="clear"></div>
    </div>
</span>
        </div>
        <div class="bd-rate-bottom">
            <div class="rsht-cxl" id="CancelPolicyWSMA0511000015CL096-CL124" onclick="sHC.rCancel('WSMA0511000015CL096-CL124','CL096-CL124');" title="Click for view cancellation policy">
                <textarea id="PolicyWSMA0511000015CL096-CL124" style="display:none"></textarea>
                Cancellation Policy         </div>
            <div class="rsht-promotion" id="FOCWSMA0511000015CL096-CL124" onmouseover="sHC.popupHotelFOC(this, 'WSMA0511000015CL096-CL124','CL096-CL124');" detail="" style="display:none;">(Special Promotion)</div>
            <div class="rsht-message" id="lyHotelMessageWSMA0511000015CL096-CL124"><blink><b><font color="red">Hotel Message</font> : </b></blink> <span id="HotelMessageWSMA0511000015CL096-CL124" style="word-wrap:break-word;">Complimentary WIFI internet access</span></div>
            <div class="clear"></div>
        </div>
    </div>

如果有另一个像这样的表结构,求值函数只返回 1 甚至 0... 那么这个案例有什么问题呢?

如果我在检查元素 chrome 浏览器中进行 jQuery dom 计数,这就是我得到的结果

jQuery("#dResult > div:nth-child("+1+") > div > div:nth-child(4) > div:nth-child("+1+") > div:nth-child(1) > span > div").length;

8

jQuery("#dResult > div:nth-child("+1+") > div > div:nth-child(4) > div:nth-child("+2+") > div:nth-child(1) > span > div").length;

15

最佳答案

您的选择器看起来不错。可能发生了很多事情...

等待

站点未完全加载(动态站点/SPA),这意味着您尝试过早访问这些元素。例如,您可以等待第一个元素出现,然后访问所有元素:

casper.waitFor(function check(){
    return this.evaluate(getNumber, 1) > 0;
}, function then(){
    var table_rows1 = this.evaluate(getNumber, 1);
    var table_rows2 = this.evaluate(getNumber, 2);
    ...
});

使用 XPath

PhantomJS 的 :nth-child() 选择器有一个错误,它只出现在特定的星座中。您可以尝试为此使用 XPath 表达式。

function getNumber(it){
     var query = "//*[@id='dResult']/*["+1+"]/div/*[4]/*["+it+"]/*[1]/span/div";
     return __utils__.getElementsByXPath(query).length;
}

我之所以使用*[x]而不是div[x]是因为XPath在根据位置查询时会考虑元素名称,但是CSS选择器不要。

不同的移动页面

有时服务器会根据用户代理字符串或视口(viewport)提供不同的页面。 PhantomJS 的默认视口(viewport)大小为 400x300。可能页面由页面 JavaScript 动态更改。

  • 检查屏幕截图 (casper.capture()) 页面是否与 Chrome 中的一样。
  • 使用casper.debugHTML()转储页面源代码并将其与 Chrome 版本进行比较。

一般问题

页面可能还有其他问题。查找各种事件处理程序的错误。请注册到 resource.errorpage.errorremote.messagecasper.page.onResourceTimeout 事件(Example)。

关于javascript - 使用 CasperJS 计算失败的 DOM 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30034367/

相关文章:

css - 使用 :after 将元素定位在其父项下

css - 如何在重复模式中选择一系列元素

javascript - `querySelectorAll` 没有 't return anything in ` casperjs`

javascript - phonegap javascript 警报不起作用?

javascript - d3.js比例符号图: setting radius of a circle based on data value

javascript - Jquery插件confirmOn不适用于ajax加载的DOM

casperjs - 如何让 Casper JS 返回指示测试成功状态的退出代码?

javascript - html 5 Canvas 文本

CSS3 不是最后一个 child 的选择器

javascript - 使 createElement 对于假标签返回 function/true