Selenium RC CSS定位器可能比XPath慢的原因?

时间:2011-04-14 22:55:32

标签: screen-scraping css-selectors selenium-rc xpath

我有一些代码可以使用SeleniumRC来模拟递归树,以便从HTML树中获取内容。我使用Xpath和CSS定位器运行代码。

树表示为一系列嵌套表。如果它很重要,一些树内容开始不可见,因为分支被“折叠”。对于Xpath和CSS,树在可见与不可见方面处于相同状态。

要获取节点值,我的代码以“root”表达式开头,添加“branch”标记,可以为每个连续的兄弟节点递增,然后使用“node”标记来获取文本内容。

一切正常,但使用我提出的CSS表达式要慢得多。

我认为这是制作定位器表达式的一种方法,尽管它适用于我的目的。我只想弄清楚如何最好地使用CSS来更接近使用Xpath的时间。

循环测试许多无效表达式(一直寻找第n个兄弟,直到找不到)并且表达式变得非常长,这是由于我逐步进一步钻进嵌套表的方式。

下面是来自递归的表达式和示例。如果有人能够提供一些关于我正在做什么的见解,那就是让CSS比Xpath花费更长的时间,这将非常有用。

对于HTML内容的这种处理我是一个全新的内容,如果你看到我从Xpath迁移到CSS的方式有些愚蠢,请说出来。

XPath“令牌”:

final String rootbase = "//*[contains(@id,\"treeBox\")]/div";
// in next string, "{branchIncrement}" will be replaced with integer values from 2 to get to text content, and skip graphical elements
final String leveltoken = "/table/tbody/tr[{branchIncrement}]/td[2]";
final String nodetoken = "/table/tbody/tr/td[4]/span";

CSS“令牌”:

final String rootbase = "css=[id*=treeBox]>div";
// in next string, "{branchIncrement}" will be replaced with integer values from 2 to get to text content, and skip graphical elements
final String leveltoken = ">table>tbody>tr:nth-child({branchIncrement})>td:nth-child(2)";
final String nodetoken = ">table>tbody>tr>td:nth-child(4)>span";

“root”中内容的第一个XPath表达式是:

//*[contains(@id,"treeBox")]/div/table/tbody/tr[2]/td[2]/table/tbody/tr/td[4]/span

具有四个级别的40个节点树的最后一个XPath表达式,每个级别低于根(1 + 3 + 3x3 + 3x3x3)的三个兄弟是:

//*[contains(@id,"treeBox")]/div/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[3]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr/td[4]/span

第一个CSS表达式是:

[id*=treeBox]>div>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr>td:nth-child(4)>span

最后一个CSS表达式是:

[id*=treeBox]>div>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(3)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr>td:nth-child(4)>span

3 个答案:

答案 0 :(得分:1)

在Firefox中,Selenium RC的XPath定位器由浏览器的本机XPath引擎处理,CSS定位器由JavaScript库(Dean Edwards' cssQuery.js)处理。后来Selenium发布(例如,2.0b *系列)使用jQuery的sizzle CSS库,但他们仍然使用JavaScript。除了隐含的速度差异之外,你在根表达式( ie [id*=treeBox)中进行模式匹配,这需要枚举整个DOM树来定位匹配,甚至在你从那里下来之前。想想你如何用纯JavaScript编写它,你就会开始看到问题。

如果它让你感觉更好,IE仍然没有本机XPath实现,所以Selenium在该浏览器中使用了几种JavaScript实现之一,并且它的速度是XPath速度的一半到十分之一因为Firefox 3.6。

很长的答案很简单,在这种特殊情况下,你可以做的很快就能让CSS定位器更快。

答案 1 :(得分:0)

通常情况下,这不是你可以帮助的。 Selenium中的XPath选择器机制使用浏览器的XPath工具。甚至IE6也有其中之一。我不知道有一个浏览器通过JavaScript提供CSS选择器工具,因此Selenium必须使用自己的代码。由于他们的代码是所有JavaScript和内部浏览器XPath解析通常在本机代码中完成,因此速度要慢得多(特别是在IE6中)。

答案 2 :(得分:0)

感谢您的反馈。阅读完笔记之后,我想知道是否可以通过使用一小段代码来解析文字Id值来替换重复使用的包含表达式来获得改进。

以下是我用于同一事物的四种不同的定位器。一对定位器是XPath,两个是CSS。对于每个对,一个使用包含表达式,一个首先解析为文字。在每种情况下,示例定位器都用于三级1307节点树的最后一个节点。

XPath with contains:

//*[contains(@id,"treeBox")]/div/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[26]/td[2]/table/tbody/tr/td[4]/span

XPath,其中文字替换包含表达式:

id('ns_7_5R4GAB1A0GKQ50IQJQR7VV10M6__treeBox')/div/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[24]/td[2]/table/tbody/tr/td[4]/span

CSS with contains:

css=[id*=treeBox]>div>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(24)>td:nth-child(2)>table>tbody>tr>td:nth-child(4)>span

文字替换的CSS包含表达式:

css=[id=ns_7_5R4GAB1A0GKQ50IQJQR7VV10M6__treeBox]>div>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(2)>td:nth-child(2)>table>tbody>tr:nth-child(24)>td:nth-child(2)>table>tbody>tr>td:nth-child(4)>span

使用两个不同大小的树,一个102个节点,另外1307个节点,我找到了以下内容。

102个节点:
       |包含|文字|
 XPath | 15秒| 13秒|
  CSS | 19秒| 19秒|

130页节点:
       |包含|文字|
 XPath | 255秒| 145秒|中文   CSS | 1893秒| 1811秒。|

显然,本机实现(使用Se-RC的Firefox上的XPath)比JScript实现快得多。折衷方案是它可能不适用于各种浏览器。