You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium VBA无法定位元素求助:需两次检查才获取目标元素

Why You Need Two Inspections to Get the Correct Element & How to Fix Selenium VBA Locator

Why Two Inspections?

The core issue here is dynamic DOM updates triggered by clicking the "By Round" button. Here's the breakdown:

  • When you first click and immediately inspect, the browser’s DevTools show the DOM state before JavaScript finishes loading the round-specific content. The target element either hasn’t been added to the DOM yet, or is still hidden (e.g., inside a container with display: none).
  • By the time you repeat the inspect, the AJAX call for round data has completed, the content has rendered, and the target element is now present and visible in the updated DOM. That’s why the second inspection gives you the correct XPath.

Some sites also use lazy loading—meaning elements aren’t created until user interaction (like your click) triggers their generation.

Fixing the Selenium VBA Code

To reliably locate the element, you need to account for the dynamic loading process. Here’s how to adjust your code:

1. Wait for the "By Round" Button & Click It Properly

First, ensure you wait for the button to be clickable before interacting with it to avoid race conditions:

Dim driver As New ChromeDriver
driver.Get "https://www.sofascore.com/tournament/football/england/premier-league/17"

' Wait up to 10 seconds for the "By Round" button to be clickable
driver.WaitUntil (WaitFor.ElementIsClickable("xpath://button[contains(text(), 'By Round')]"), 10000)
driver.FindElementByXPath("//button[contains(text(), 'By Round')]").Click

2. Use Explicit Waits for the Target Element

Never rely on Thread.Sleep—use Selenium’s built-in wait methods to wait until the target element is present and visible. This ensures you only interact with it once it’s fully rendered:

' Wait up to 10 seconds for your target element to become visible (replace with your XPath)
driver.WaitUntil (WaitFor.ElementIsVisible("xpath://your-target-element-xpath"), 10000)
Dim targetElement As WebElement
Set targetElement = driver.FindElementByXPath("//your-target-element-xpath")

3. Use a More Stable Locator

Absolute XPaths (like /html/body/div[3]/div[2]/...) are fragile—they break if the DOM structure changes. Instead, use:

  • Partial text matches: //div[contains(text(), 'Round 1')]
  • Unique attributes: Look for data-testid, class, or id attributes specific to the element (check your second inspect result for these). For example:
    driver.FindElementByCssSelector("[data-testid='round-item-1']")
    

4. Handle Hidden Elements (Last Resort)

If the element exists in the DOM but is hidden, you can use JavaScript to make it visible before interacting:

If driver.ElementExists("xpath://your-target-element-xpath") Then
    driver.ExecuteScript "arguments[0].style.display = 'block';", driver.FindElementByXPath("//your-target-element-xpath")
    ' Now interact with the element
End If

Example Full Code

Putting it all together:

Sub ScrapePremierLeagueRounds()
    Dim driver As New ChromeDriver
    driver.Start "chrome"
    driver.Get "https://www.sofascore.com/tournament/football/england/premier-league/17"
    
    ' Accept cookies (adjust locator if needed)
    On Error Resume Next
    driver.WaitUntil (WaitFor.ElementIsClickable("xpath://button[contains(text(), 'Accept')]"), 5000)
    driver.FindElementByXPath("//button[contains(text(), 'Accept')]").Click
    On Error GoTo 0
    
    ' Click "By Round" button
    driver.WaitUntil (WaitFor.ElementIsClickable("xpath://button[contains(text(), 'By Round')]"), 10000)
    driver.FindElementByXPath("//button[contains(text(), 'By Round')]").Click
    
    ' Wait for round elements to load
    driver.WaitUntil (WaitFor.ElementIsVisible("xpath://div[contains(@class, 'RoundSelector_round')]"), 10000)
    
    ' Get all round elements and print their names
    Dim rounds As WebElements
    Set rounds = driver.FindElementsByXPath("//div[contains(@class, 'RoundSelector_round')]")
    
    Dim round As WebElement
    For Each round In rounds
        Debug.Print round.Text
    Next round
    
    driver.Quit
End Sub

Key Takeaways

  • The double inspection issue stems from dynamic DOM updates after user interaction.
  • Always use explicit waits instead of hard-coded delays to handle dynamic content.
  • Prefer stable locators (CSS selectors, attribute-based XPaths) over absolute XPaths.
  • Ensure the element is visible before trying to interact with it.

内容的提问来源于stack exchange,提问作者Lucas Guedes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:02:10