如果我在 Selenium 中加载页面,然后我必须对此页面执行 100 个不同的解析请求,我该怎么办?
此时我使用不同的 driver.findElement(By...)
,问题是每次都是从 java 到 selenium 的 http (get/post)
请求。从这个案例来看,一个简单的页面解析花费了我 30 多秒(太多了)。
我认为我必须从第一个请求获取源代码(driver.getPageSource()
),然后在本地解析该字符串(我的页面在解析时不会更改)。
- 我可以从此字符串构建某种 HTML 对象以继续处理 WebElement 请求吗?
- 我必须使用另一个库来构建 HTML 对象吗? (例如 - jsoup)在这种情况下,我将不得不从 webelement 和 XPath 重建我的解析请求。
- 还有什么吗?
最佳答案
当您调用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
rigmarole是因为.getElementsByClassName
返回的东西的行为类似于Array
,但它不是 Array
,因此它没有 .filter
方法。)
如果您知道页面在检查时不会更改,则可以选择本地解析。您应该使用以下内容获取页面的源代码:
String html = (String) ((JavascriptExecutor) driver).executeScript(
"return document.documentElement.outerHTML");
通过执行此操作,您可以完全按照浏览器解释的方式查看页面。您必须使用 Selenium 以外的其他工具来解析 HTML。
关于java - 如何加快 Selenium 中的页面解析速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31672742/