首页 > 解决方案 > 网页上的按钮不可点击

问题描述

前段时间我问过一个问题,但我在尝试解析网页时仍然面临随机错误。场景是系统转到https://www.sprouts.com/store/tx/plano/plano/点击“查看这家商店的特价商品”导航到https://shop.sprouts.com/shop/flyer和提取商店特价商品。目前,下面的代码仅在 10% 或 20% 的情况下有效,因为它无法找到要单击的按钮并导航到下一页。我究竟做错了什么?

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using OpenQA.Selenium;
    using OpenQA.Selenium.Chrome;
    using OpenQA.Selenium.Support.UI;
    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using SeleniumExtras.WaitHelpers;

      [TestClass]
      public class UnitTest1
      {
        ChromeDriver driver;
        WebDriverWait webDriverWait;
        [TestInitialize]
        public void Startup()
        {
          var chromeOptions = new ChromeOptions();
          //chromeOptions.AddArguments("headless");
          chromeOptions.AddArguments("--proxy-server='direct://'");
          chromeOptions.AddArguments("--proxy-bypass-list=*");
          //chromeOptions.AddUserProfilePreference("disable-popup-blocking", "true");
          //chromeOptions.AddArguments("--disable-extensions");
          chromeOptions.AddArguments("--start-maximized");

          var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
          ChromeDriverService chromeDriverService = ChromeDriverService.CreateDefaultService(path);
          driver = new ChromeDriver(chromeDriverService, chromeOptions);
          webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
        }
        [TestCleanup]
        public void CleanUp()
        {
          driver.Quit();
        }
        [TestMethod]
        public void GetSproutsWeeklyAdDetails()
        {   
          try
          {        driver.Navigate().GoToUrl("http://www.sprouts.com/store/tx/plano/plano/");
          }
          catch (TimeoutException timeoutException)
          {
            driver.Navigate().Refresh();
          }
          webDriverWait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
          **var elements1 = webDriverWait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(
            By.XPath("//div[@class='cell small-6 divider']/button")));
          elements1.First().Click();**
    <= the system is unable to find the button 80% of the times

          webDriverWait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
          var elements2 = webDriverWait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(
            By.XPath("//li[@class='cell-wrapper' and @ng-repeat='item in items track by $index']"))); 
//More code below    
          }
        }
      }

不可点击按钮所在区域的源代码:

<div class="cell small-6 divider">        
        <button onclick="viewStoreFlyer(event, 101)">
          <img src="https://www.sprouts.com/wp-content/themes/FoundationPress/dist/assets/images/weekly-specials-stores-icon.svg" width="32" alt="" role="presentation">
          <br>
          View this store’s specials
        </button>        
      </div>

标签: c#.netseleniumselenium-chromedriver

解决方案


在我看来,代码几乎是好的,除了两件事。您正在等待所有元素都可见,然后立即想要单击其中的第一个。首先在网站上只有一个元素跟随xPath,所以不需要定位列表。第二个是 - 当元素可见时,并不意味着它是可点击的,因此更好的处理方法是:

webDriverWait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div[@class='cell small-6 divider']/button"))); 

PS: @DebanjanB 提供的答案在这种情况下非常好,因为您只想提取文本而不与元素交互。在我们的例子中,我们必须等到元素准备好接收点击,这就是为什么ElementToBeClickable在这种情况下更好。


推荐阅读