计数 DOM 个 CasperJS 评估失败的元素
Count DOM elements with CasperJS' evaluate failed
我刚刚遇到 CasperJS 的问题。
我需要计算 table 行,因为有很多 table 包含相同的信息结构(比如说用户 table)
所以我做了一些 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);
它是迭代器,它会递增直到达到table个元素长度。
所以假设我们有 3 个 table,所以它将是 1,2,3
对于它 = 1,没有问题发生,它打印出正确的 table[1] 行数。
但是对于下一个,2,3,它只为 table 行号打印 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 个 table 的,有很多 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>
如果还有另一个像这样的table结构,求值函数只是return 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
您的选择器看起来不错。可能发生了很多事情...
正在等待
站点未完全加载(动态 site/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选择器不会。
不同的移动页面
有时服务器会根据用户代理字符串或视口提供不同的页面。 PhantomJS 的默认视口大小为 400x300。可能页面被页面 JavaScript.
动态更改了
- 检查屏幕截图 (
casper.capture()
) 页面看起来是否与 Chrome 中的相同。
- 使用
casper.debugHTML()
转储页面源并将其与 Chrome 版本进行比较。
一般问题
页面可能还有其他问题。查找各种事件处理程序的错误。请注册参加 resource.error
、page.error
、remote.message
和 casper.page.onResourceTimeout
活动 (Example)。
我刚刚遇到 CasperJS 的问题。
我需要计算 table 行,因为有很多 table 包含相同的信息结构(比如说用户 table) 所以我做了一些 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);
它是迭代器,它会递增直到达到table个元素长度。
所以假设我们有 3 个 table,所以它将是 1,2,3 对于它 = 1,没有问题发生,它打印出正确的 table[1] 行数。 但是对于下一个,2,3,它只为 table 行号打印 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 个 table 的,有很多 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>
如果还有另一个像这样的table结构,求值函数只是return 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
您的选择器看起来不错。可能发生了很多事情...
正在等待
站点未完全加载(动态 site/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选择器不会。
不同的移动页面
有时服务器会根据用户代理字符串或视口提供不同的页面。 PhantomJS 的默认视口大小为 400x300。可能页面被页面 JavaScript.
动态更改了- 检查屏幕截图 (
casper.capture()
) 页面看起来是否与 Chrome 中的相同。 - 使用
casper.debugHTML()
转储页面源并将其与 Chrome 版本进行比较。
一般问题
页面可能还有其他问题。查找各种事件处理程序的错误。请注册参加 resource.error
、page.error
、remote.message
和 casper.page.onResourceTimeout
活动 (Example)。