Selenium webdriver读取时间太长



我打开了一个不和谐音频道,正忙着用下面的语句从它循环读取消息以获取元素:

List<org.openqa.WebElement> ret = driver.findElement(By.tagName("main")) // driver = WebDriver
.findElements(By.tagName("li"))
.stream()
.filter(message -> message.getAttribute("id") != null
&& message.getAttribute("id").contains("chat-messages"))
.toList();

页面默认显示约40条消息,每次读取需要5-6秒。它长得令人无法接受。我读到,当没有匹配时,finelement有一个隐式的等待时间,但这里的情况并非如此,因为每次读取都会返回元素。你知道是什么导致了这种延迟,如何改进吗?

更新:从我收到的第一个答案开始,我尝试了

List<WebElement> ret = driver.findElements(By.xpath("//main//li[contains(@id,'chat-messages')]"));

起初它看起来好像很快,但很快我意识到这一定是一些暂时的事情。它花的时间和以前一样长

更新:遗憾的是,经过一些调试,我发现驱动程序。finelements不是需要几秒钟的,它只需要不到20毫秒,但是我有一些代码从所有返回元素的远程web元素读取属性,这就是导致延迟的原因。我现在已经重新构造了代码,它只具有从findElements返回的最后一条消息的读取属性,并维护其时间戳,以便下次识别新消息。

List<WebElement> ret = driver.findElements(By.xpath("//main//li[contains(@id,'chat-messages')]"));

与其一次检索一个元素,不如让xpath完成这项工作并在一次调用中检索所有元素。

尝试使用cssSelector的结果和性能。

像这样:

List<WebElement> elements = driver.findElements(By.cssSelector("main [id^=chat-message]"));

或甚至没有main

List<WebElement> elements = driver.findElements(By.cssSelector("[id^=chat-message]"));

PageLoadStrategy:您是否尝试更改PageLoadStrategy?它可能不会很慢,因为您尝试接收的元素数量,但因为Selenium也在等待Document.readyState

默认情况下,硒的PLS是等待页面返回complete,但许多新的web应用程序是异步的(AJAX),并且已经返回正确的元素,而浏览器的readyState仍然在interactive

要将PLS设置为查找元素而不等待complete的模式,您需要更改默认选项。对于Chrome,可以这样做:

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setPageLoadStrategy(PageLoadStrategy.NONE);
WebDriver driver = new ChromeDriver(chromeOptions);
  1. 获取此信息的最快速方法是通过直接调用API来完成此操作,而不是从GUI元素中读取。
  2. 使用BeautifulSoup读取这些数据比使用Selenium更慢,但仍然更快。
  3. 如果页面长加载时间是由页面上的某些脚本引起的,您可以将页面加载策略设置为EAGER,这将大大减少这种延迟。
  4. 您可以使用Headless浏览器。在此模式下,Selenium驱动程序比在常规可见模式下执行得更快。

您说您知道隐式等待,但是您是否尝试过减少它?我过去在查找多个元素时也遇到过类似的问题。请根据您的语言查看文档。

driver.implicitly_wait(0.1) // depends on language
List<org.openqa.WebElement> ret = driver.findElement(By.tagName("main")) // driver = WebDriver
.findElements(By.tagName("li"))
.stream()
.filter(message -> message.getAttribute("id") != null
&& message.getAttribute("id").contains("chat-messages"))
.toList();

最新更新