4

I'm trying to automate an action on my website. Every so often, I want a bot to visit certain pages and click an element. Sometimes, this element isn't there, and that breaks the whole thing because the bot doesn't know what to do. Ideally, I'd like to record how many times the element isn't there, but at minimum I'd like the bot to skip that page and keep going.

Here's what I have so far:

require "selenium-webdriver"
require "nokogiri"
driver = Selenium::WebDriver.for :chrome
wait = Selenium::WebDriver::Wait.new(:timeout => 19)


User.all.each do |u|
  driver.navigate.to "http://website.com/" + u.name
  driver.find_element(:class, "like").click #THIS IS THE LINE THAT SOMETIMES FAILS
end
browser.close

So ideally, in place of just driver.find_element(:class, "like").click, I'd like something like:

if element(:class, "like").exists?
  driver.find_element(:class, "like").click
else
  u.error = true
  u.save
end

Is that possible?

Joe Morano
  • 1,715
  • 10
  • 50
  • 114

3 Answers3

5

Following @max pleaner advice, you could rescue the exception about not finding the element and then do something with that information. The exception you are looking for in this case is NoSuchElementError.

The code could look like this:

User.all.each do |u|
  driver.navigate.to "http://website.com/" + u.name
  begin
   driver.find_element(:class, "like").click #THIS IS THE LINE THAT SOMETIMES FAILS
  rescue Selenium::WebDriver::Error::NoSuchElementError
    u.error = true
    u.save
  end
end
chipairon
  • 2,031
  • 2
  • 19
  • 21
3

yes.its possible.try the following code

User.all.each do |u|
  driver.navigate.to "http://website.com/" + u.name
if driver.find_elements(:class, "like").count > 1
  driver.find_element(:class, "like").click
end
end

you can also ensure the continuity through exception handling in ruby like begin rescue ensure

Community
  • 1
  • 1
Joe Sebin
  • 452
  • 4
  • 24
2

It's really a simple fix here:

Take this:

  driver.find_element(:class, "like").click

and change it to this if your Ruby is 2.3 or newer

  # the &. here is the 'safe navigation operator'
  driver.find_element(:class, "like")&.click

or this for older versions of ruby:

  element = driver.find_element(:class, "like")
  element.click if element

or for your the case when you're doing some conditional db logic:

  element = driver.find_element(:class, "like")
  if element
    # do something in the database
  else
    # something else in the database
  end

More generally, you can use typical Ruby control flow to skip nokogiri / commands. Check if the array is empty, check if the key exists, etc. If you foresee an error being raised, rescue that specific error.

max pleaner
  • 26,189
  • 9
  • 66
  • 118