如何在Selenium中加速页面解析

时间:2015-07-28 09:44:57

标签: java selenium

如果我在Selenium中加载页面然后我必须对此页面进行100次不同的解析请求,我该怎么办?
此时我使用不同的driver.findElement(By...),问题是每次从java进入selenium的http (get/post)请求。从这个案例中,一个简单的页面解析花费了我30+秒(太多) 我认为我必须从第一个请求获取源代码(driver.getPageSource()),然后在本地解析此字符串(我的页面在解析时不会改变)。

  • 我可以从此字符串构建某种HTML对象以继续处理WebElement请求吗?
  • 我是否必须使用其他lib来构建HTML对象? (例如-jsoup)在这种情况下,我将不得不重建来自webelement&XPath和XPath的解析请求。
  • 还有别的吗?

2 个答案:

答案 0 :(得分:2)

当您致电findElement时,Selenium无需解析页面以查找元素。加载页面时会发生HTML解析。由于JavaScript对页面的修改(如执行element.innerHTML += ...时),可能会进行一些进一步的解析。 Selenium所做的是使用.getElementsByClassName.querySelector等方法查询DOM。这就是说,如果您的浏览器加载到远程计算机上,事情就会变慢。即使在本地,如果你在Selenium脚本和浏览器之间进行大量的往返,它也会影响脚本的速度。你能做什么?

当我在页面上进行大量查询时,我更喜欢做的是使用.executeScript来完成浏览器端的工作。这可以将几十个查询减少到一个查询。例如:

List<WebElement> elements = (List<WebElement>) ((JavascriptExecutor) driver)
  .executeScript(
    "var elements = document.getElementsByClassName('foo');" + 
    "return Array.prototype.filter.call(elements, function (el) {" + 
    "  return el.attributes.whatever.value === 'something';" +
    "});");

(我没有运行上面的代码。请注意拼写错误!)

在此示例中,您将获得类foo的所有元素的列表,这些元素具有名为whatever的属性,其值等于something。 (Array.prototype.filter.call严重性是因为.getElementsByClassName返回的行为类似于Array,但不是Array,因此它没有.filter方法。)

如果您知道页面在检查时不会更改,则可以选择本地解析。您应该使用以下内容获取页面的来源:

String html = (String) ((JavascriptExecutor) driver).executeScript(
    "return document.documentElement.outerHTML");

通过执行此操作,您可以完全按照浏览器解释它的方式查看页面。您将不得不使用Selenium之外的其他内容来解析HTML。

答案 1 :(得分:0)

也许只有在尝试使用它们时才尝试评估元素? 我不知道Java等价物,但在C#中你可以做类似下面的事情,它只会在使用时查找元素:

private static readonly By UsernameSelector = By.Name("username");

private IWebElement UsernameInputElement
{
    get { return Driver.FindElement(UsernameSelector); }
}