如何让 Selenium/Ruby 机器人在执行操作之前等待?

Posted

技术标签:

【中文标题】如何让 Selenium/Ruby 机器人在执行操作之前等待?【英文标题】:How to get a Selenium/Ruby bot to wait before performing an action? 【发布时间】:2016-06-16 03:49:21 【问题描述】:

我正在构建一个单击元素的 Selenium/Ruby 网络机器人。问题是,有时在机器人决定它找不到元素之前没有足够的时间加载页面。

在执行操作之前让 Selenium 等待的 Ruby 方法是什么?我更喜欢显式等待,但我也可以接受隐式等待。


我尝试使用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

但我收到以下错误:

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

我也试过了:

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

但这也给了我一个未定义的方法错误:

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

【问题讨论】:

如果你刚刚开始,切换到水豚。 Capybara 默认等待,在后台使用 selenium(或其他驱动程序),API 易于使用。 【参考方案1】:

随便用

sleep(number_of_seconds)

那你就等着吧。

【讨论】:

【参考方案2】:

你有没有试过当出现时,等待按钮(你也可以让它等待某个 div 到)

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

至于显式等待

sleep *seconds*

或者更好的方式来不浪费时间

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

【讨论】:

它给了我一个“未定义的方法`when_present'”错误。 我认为您实际上指的是显式等待【参考方案3】:

好的。这个答案在许多不同的情况下被问过很多次。所以我只想在这里一劳永逸地回答。

这可以通过三种方式完成。并且每一个都在某些情况下很有用。

首先,您可以使用显式等待。这与页面是否加载无关。它只是告诉脚本等待。换言之,如果您的页面加载时间为 11 秒,而您的显式等待时间为 10 秒,则可点击元素 still 将不可用。您可以通过使用预期条件来解决这种低效率问题。例如,参见 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

^ 这将等待:10 秒或直到找到元素。

第二,你可以使用隐式等待。这与具有预期条件的显式等待非常相似。但是,显式等待适用于被查询的元素,隐式等待适用于 WebDriver 对象。换句话说,如果您的脚本只使用一个 webdriver,它将等待:每个元素的隐式等待时间或直到找到每个元素(直到失败)。例如:

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

第三,可以调用javascript函数来点击页面。这样做的好处是一旦页面的 Javascript 加载,该项目将是可点击的,您不必真正等待页面呈现。很多时候,当您“等待页面”时,实际上是在 客户端 端等待渲染引擎构建页面。您可以通过在页面实际呈现之前简单地单击底层元素来绕过该过程。

这样做的缺点是它不能反映实际的人类点击页面。例如,如果您要单击的按钮被弹出窗口隐藏。 Selenium 不允许你点击它,但是一个 JS 函数可以。

您可以通过以下方式使用此方法:

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

【讨论】:

【参考方案4】:

可能的答案在您的堆栈跟踪中。

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

【讨论】:

【参考方案5】:

您正在使用wait 作为WebDriver 函数,但事实并非如此。试试这个

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

【讨论】:

以上是关于如何让 Selenium/Ruby 机器人在执行操作之前等待?的主要内容,如果未能解决你的问题,请参考以下文章

实操体验 CPU 的流水线/多发射

Selenium+Ruby 实例分析 - 京东抢券 2 处理cookie

Net::ReadTimeout (Net::ReadTimeout) Selenium Ruby

让 ssh 在目标机器的后台执行命令

使用 selenium ruby​​ capybara 拖放

Selenium ruby常用api