Selenium VBA无法定位元素求助:需两次检查才获取目标元素
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, oridattributes 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

