How to get a Selenium/Ruby bot to wait before performing an action?

前端 未结 7 772
Happy的楠姐
Happy的楠姐 2020-12-16 21:28

I\'m building a Selenium/Ruby web bot that clicks on elements. The problem is, sometimes there isn\'t enough time for the page to load before the bot decides it can\'t find

相关标签:
7条回答
  • 2020-12-16 22:10

    You can also simply use sleep(#) this will cause it to wait, and depending on your editor you can see which variations you can use so instead of seconds you can go to something lower or higher, in Ruby you don't even have to declare it.

    Just type sleep and a number in the parenthesis and you should see it stop for that amount of time in seconds, others note why this is a solution that might not be optimal, but if you only need it to wait for a bit on a page that will never take that long it's great one line code to use.

    0 讨论(0)
  • 2020-12-16 22:11

    Have you tried the when present, to wait for the button (You could also make it wait for a certain div to )

    require "watir-webdriver/wait"
    driver.button(:class => 'gb_P').when_present.click
    

    As for explicit waiting

    sleep *seconds*
    

    or a better way as to not waste time

    sleep *seconds* until driver.element(:id/class/etc, 'value').exists?
    
    0 讨论(0)
  • 2020-12-16 22:26

    Okay. This answer has been asked many times in many different contexts. So I just want to answer it here once and for all.

    There are three ways this can be done. And each is useful in certain contexts.

    First, you can use an EXPLICIT wait. This has nothing to do with whether the page loads or not. It simply tells the script to wait. In other words, if your page loads in 11 seconds and your explicit wait is 10 seconds, the clickable element still won't be available. You can work around this inefficiency by using an expected condition. See, e.g., the Selenium manpages:

    require 'selenium-webdriver'
    
    driver = Selenium::WebDriver.for :firefox
    driver.get "http://google.com"
    
    wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
    begin
      element = wait.until { driver.find_element(:class => "gb_P") }
    ensure
      driver.quit
    end
    

    ^ This will wait either: 10 seconds OR until the element is found.

    Second, you can use an implicit wait. This is very similar to the explicit wait with expected condition. However, where the explicit waits applies to the element being queried, implicit wait applies to the WebDriver Object. In other words, if your script only uses a single webdriver, it will wait either: the implicit wait time for EVERY element OR until each element is found (until failure). For example:

    require 'selenium-webdriver'
    
    driver = Selenium::WebDriver.for :firefox
    driver.manage.timeouts.implicit_wait = 10 # seconds
    
    driver.get "http://google.com"
    element = driver.find_element(:class => "gb_P")
    

    Third, you can call a Javascript function to click the page. The advantage of this is that once the page's Javascript loads, the item will be clickable and you don't have to actually wait for the page to render. A lot of time when you're "waiting for the page" you're actually waiting on the client side for the rendering engine to construct the page. You can bypass that process by simply clicking the underlying element before the page is actually rendered.

    The drawback of this is that it doesn't mirror an actual human clicking the page. For example, if the button you want to click is hidden by a popup. Selenium won't allow you to click it, but a JS function will.

    You can use this method by doing:

    click = driver.execute_script("document.getElementsByClassName('gb_P')[0].click();")
    
    0 讨论(0)
  • 2020-12-16 22:27

    You are using wait as WebDriver function, but it isn't. Try this

    element = wait.until { driver.find_element(:class => "gb_P") }
    element.click
    
    0 讨论(0)
  • 2020-12-16 22:29

    A potential answer is in your stacktrace.

    driver.element(:class, "gb_P").when_present.click
    
    0 讨论(0)
  • 2020-12-16 22:30

    Using Webdriver RC and C# I find this is the most effective way to make the driver wait:

    Task.Delay(1000).Wait();
    
    0 讨论(0)
提交回复
热议问题