Ruby Selenium Webdriver - 页面重定向时需要等待/休眠(刷新)

时间:2014-07-01 14:21:10

标签: ruby selenium-webdriver

我使用Ruby selenium-webdriver gem创建了一个网络抓取/抓取脚本。我通过AJAX加载我抓取的页面并显示某个帐户的信息。如果您在下拉菜单中选择第二个帐号,页面会非常简短地重定向到另一个URL并返回到原始URL,只需通过AJAX加载不同的信息。我希望能够抓取下拉选项中列出的帐号的信息。问题是,Selenium执行抓取的速度比网页在下拉列表中重定向/重新加载的速度快,因此我不会获得第二个帐户的信息。

def crawl_page
  browser = Selenium::WebDriver.for :firefox
  browser.manage.timeouts.implicit_wait = 10 # seconds 
  browser.navigate.to 'http://www.foobar.com'
  account_dropdown = Selenium::WebDriver::Support::Select.new(browser.find_element(:id, 'account'))
  account_dropdown.options.each do |option|
    option.click
    wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
    # this wait is not working because option is selected before redirect/refresh:
    wait.until { option.selected? }
    html = browser.page_source
    scrape_page(html)
  end
  browser.quit  
end

我在点击后尝试在行上放置sleep(3),但收到以下错误消息:

[remote server] resource://fxdriver/modules/web_element_cache.js:8180:in `fxdriver.cache.getElementAt': Element not found in the cache - perhaps the page has changed since it was looked up (Selenium::WebDriver::Error::StaleElementReferenceError)

我也尝试使用Selenium的显式wait代码,但元素的ID似乎在更新后的页面上动态更改,如下所示:

wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
wait.until { browser.find_element(:id, 'titlexyz').displayed? }

会出现一条错误消息,指出它已超时,无法找到该元素:

~lib/selenium/webdriver/common/wait.rb:57:in `until': timed out after 10 seconds (Unable to locate element: {"method":"id","selector":"titlexyz"}) (Selenium::WebDriver::Error::TimeOutError)

有没有办法让它入睡或等待,而无需在页面上寻找特定的元素?

2 个答案:

答案 0 :(得分:2)

好的,所以我终于明白了,感谢SiKing的回答。诀窍是计算下拉菜单的选项数量,并将其放入.times循环。然后在每次迭代中,我为下拉菜单实例化一个新的Selenium对象,找到正确的选项号并单击它。我还让脚本睡了5秒钟,让它有机会进行重载/重定向。

def crawl_page
  browser = Selenium::WebDriver.for :firefox
  browser.navigate.to 'http://www.foobar.com'
  account_dropdown = Selenium::WebDriver::Support::Select.new(browser.find_element(:id, 'account'))

  count = account_dropdown.options.count
  count.times do |option_num|
    account_dropdown = Selenium::WebDriver::Support::Select.new(browser.find_element(:id, 'account'))
    account_dropdown.options[option_num].click
    sleep 5
    html = browser.page_source
    scrape_page(html)
  end

  browser.quit  
end

答案 1 :(得分:0)

我不做ruby,所以我无法帮助你使用ruby语法。

每次页面重新加载(每次执行option.click时都会在您的代码中),您拥有的所有WebElements(您的account_dropdown.find_elements(:css, 'option'))都不再有效!你必须将你的循环基于其他东西 - 也许是下拉项目的数量 - 并找到你想与内部交互的每个元素!