【问题标题】:Reasons why SeleniumRC CSS locators might be slower than XPath?SeleniumRC CSS 定位器可能比 XPath 慢的原因是什么?
【发布时间】:2011-08-05 22:51:37
【问题描述】:

我有一些代码可以模拟递归树遍历,以使用 SeleniumRC 从 HTML 树中抓取内容。我已经使用 Xpath 和 CSS 定位器运行了代码。

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

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

一切正常,但使用我想出的 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";

“根”处内容的第一个 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

【问题讨论】:

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


    【解决方案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 定位器更快。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 在这种情况下,它是 SeleniumRC 到 Firefox 3.6.15。
      • 还是会慢一些。与原生 XPath 相比,FF 3.6 的 JavaScript 引擎速度较慢。 Firefox 4 有一个更快的 JS 引擎,所以你可能会在那里看到更好的结果,但据我所知 Selenium 还不支持 FF 4。我听说它在路线图上。
      • 与我之前的假设相反,(本机)XPath 将是最快的,但不太可能在不同的浏览器中正常工作。这与我所看到的一致,谢谢!
      【解决方案3】:

      感谢您的反馈。阅读您的笔记后,我想知道是否可以通过使用一点点代码来解析文字 Id 值来替换重复使用的 contains 表达式,从而获得实质性的改进。

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

      XPath 包含:

      //*[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 包含:

      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 秒。 |

      1307 个节点:
      |包含 |字面意思 |
      XPath | 255 秒。 | 145 秒|
      CSS | 1893 秒。 | 1811 秒|

      显然,本机实现(带有 Se-RC 的 Firefox 上的 XPath)比 JScript 实现快得多。权衡是它可能无法在浏览器中正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-16
        • 2021-09-01
        • 2012-01-01
        • 2016-04-03
        相关资源
        最近更新 更多