Thursday, April 14, 2016

How can I perform an action based on the contents of a div with Selenium Webdriver?

Leave a Comment

I have a Ruby application using Selenium Webdriver and Nokogiri. I want to choose a class, and then for each div corresponding to that class, I want to perform an action based on the contents of the div.

For example, I'm parsing the following page:

https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies 

It's a page of search results, and I'm looking for the first result with the word "Adoption" in the description. So the bot should look for divs with className: "result", for each one check if its .description div contains the word "adoption", and if it does, click on the .link div. In other words, if the .description does not include that word, then the bot moves on to the next .result.

This is what I have so far, which just clicks on the first result:

require "selenium-webdriver" require "nokogiri" driver = Selenium::WebDriver.for :chrome driver.navigate.to "https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies" driver.find_element(:class, "link").click 

3 Answers

Answers 1

You can get list of elements that contains "adopt" and "Adopt" by XPath using contains() then use union operator (|) to union results from "adopt" and "Adopt". See code below:

driver = Selenium::WebDriver.for :chrome driver.navigate.to "https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies" sleep 5 items  = driver.find_elements(:xpath,"//div[@class='g']/div[contains(.,'Adopt')]/h3/a|//div[@class='g']/div[contains(.,'adopt')]/h3/a") for element in items     linkText = element.text     print linkText     element.click end 

Answers 2

The pattern to handle each iteration will be determined by the type of action executed on each item. If the action is a click, then you can't list all the links to click on each of them since the first click will load a new page, making the elements list obsolete. So If you wish to click on each link, then one way is to use an XPath containing the position of the link for each iteration:

# iteration 1 driver.find_element(:xpath, "(//h3[@class='r']/a)[1]").click   # click first link  # iteration 2 driver.find_element(:xpath, "(//h3[@class='r']/a)[2]").click   # click second link 

Here is an example that clicks on each link from a result page:

require 'selenium-webdriver'  driver = Selenium::WebDriver.for :chrome wait = Selenium::WebDriver::Wait.new(timeout: 10000)  driver.navigate.to "https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies"  # define the xpath search_word = "Puppies" xpath = ("(//h3[@class='r']/a[contains(.,'%s')]" % search_word) + ")[%s]"  # iterate each result by inserting the position in the XPath i = 0 while true do    # wait for the results to be loaded   wait.until {driver.find_elements(:xpath, "(//h3[@class='r']/a)[1]").any?}    # get the next link   link = driver.find_elements(:xpath, xpath % [i+=1]).first   break if !link    # click the link   link.click    # wait for a new page   wait.until {driver.find_elements(:xpath, "(//h3[@class='r']/a)[1]").empty?}    # handle the new page   puts "Page #{i}: " + driver.title    # return to the main page   driver.navigate.back end  puts "The end!" 

Answers 3

I don't code in ruby, but one way you could do it in python is:

driver.find_elements 

notice how elements is plural, I would grab all the links and put them into an array like.

href = driver.find_elements_by_xpath("//div[@class='rc]/h3/a").getAttribute("href"); 

Then get all of the descriptions the same way. Do a for loop for every element of description, if the description has the word "Adoption" in it navigate to that website.

for example:

if description[6] has the word adoption find the string href[6] and navigate to href[6].

I hope that makes sense!

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment