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