source rails code chromedriver chrome ruby selenium selenium-webdriver webdriver bots

rails - ¿Cómo hacer para que un robot Selenium/Ruby espere antes de realizar una acción?



selenium source (5)

Estoy construyendo un robot web Selenium / Ruby que hace clic en los elementos. El problema es que a veces no hay suficiente tiempo para cargar la página antes de que el bot decida que no puede encontrar el elemento.

¿Cuál es la forma Ruby de esperar a que el selenio espere antes de realizar una acción? Preferiría esperar explícitamente, pero estoy bien con la espera implícita también.

Traté de usar el método wait.until :

require "selenium-webdriver" require "nokogiri" driver = Selenium::WebDriver.for :chrome wait = Selenium::WebDriver::Wait.new(:timeout => 15) driver.navigate.to "http://google.com" driver.wait.until.find_element(:class, "gb_P").click

Pero me aparece el siguiente error:

Undefined method ''wait'' for <Selenium::WebDriver>

También probé:

require "watir-webdriver/wait" ... driver.find_element(:class, "gb_P").wait_until.click

pero eso también me está dando un error de método indefinido:

undefined method `when_present'' for #<Selenium::WebDriver...>


Estás usando wait como función WebDriver , pero no es así. Prueba esto

element = wait.until { driver.find_element(:class => "gb_P") } element.click


Una respuesta potencial está en tu stacktrace.

driver.element(:class, "gb_P").when_present.click


Bueno. Esta respuesta se ha preguntado muchas veces en muchos contextos diferentes. Así que solo quiero responder aquí de una vez por todas.

Hay tres formas en que esto se puede hacer. Y cada uno es útil en ciertos contextos.

Primero , puede usar una espera EXPLÍCITA. Esto no tiene nada que ver con si la página se carga o no. Simplemente le dice al script que espere. En otras palabras, si su página se carga en 11 segundos y su espera explícita es de 10 segundos, el elemento en el que se puede hacer clic todavía no estará disponible. Puede evitar esta ineficiencia utilizando una condición esperada. Ver, por ejemplo, las páginas de manual de Selenium:

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

^ Esto esperará: 10 segundos O hasta que se encuentre el elemento.

En segundo lugar , puede usar una espera implícita. Esto es muy similar a la espera explícita con la condición esperada. Sin embargo, cuando la espera explícita se aplica al elemento que se consulta, la espera implícita se aplica al Objeto WebDriver . En otras palabras, si su script solo usa un único controlador de web, esperará: el tiempo de espera implícito para CADA elemento O hasta que se encuentre cada elemento (hasta que falle). Por ejemplo:

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")

En tercer lugar , puede llamar a una función de Javascript para hacer clic en la página. La ventaja de esto es que una vez que se carga el Javascript de la página, se puede hacer clic en el elemento y no tienes que esperar a que la página se muestre . Cuando está "esperando la página", en realidad está esperando en el lado del cliente que el motor de representación construya la página. Puede omitir ese proceso simplemente haciendo clic en el elemento subyacente antes de que realmente se represente la página.

El inconveniente de esto es que no refleja un ser humano real al hacer clic en la página. Por ejemplo, si el botón que desea hacer clic está oculto por una ventana emergente. El selenio no le permitirá hacer clic en él, pero sí lo hará una función JS.

Puede usar este método haciendo:

click = driver.execute_script("document.getElementsByClassName(''gb_P'')[0].click();")


¿Has probado el presente para esperar el botón (también puedes esperar a que cierto div lo haga)

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

En cuanto a la espera explícita

sleep *seconds*

o una mejor manera de no perder el tiempo

sleep *seconds* until driver.element(:id/class/etc, ''value'').exists?


También puedes usar sleep (#) para esperar, y dependiendo de tu editor puedes ver qué variaciones puedes usar para que en lugar de segundos puedas ir a algo más bajo o más alto, en Ruby ni siquiera tienes declararlo

Simplemente escriba sleep y un número en el paréntesis y debería ver que se detiene durante ese tiempo en segundos, otros señalan por qué esta es una solución que podría no ser óptima, pero si solo lo necesita esperar un poco en una página eso nunca llevará tanto tiempo, es un gran código de una línea para usar.