2016-03-03 23 views
5

Ho un'applicazione Ruby che utilizza Selenium Webdriver e Nokogiri. Voglio scegliere una classe, e poi per ogni div corrispondente a quella classe, voglio eseguire un'azione basata sul contenuto della div.Come posso eseguire un'azione in base al contenuto di un div con Selenium Webdriver?

Ad esempio, sto analizzando la seguente pagina:

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

Si tratta di una pagina di risultati di ricerca, e sto cercando il primo risultato con la parola "adozione" nella descrizione. Quindi il bot dovrebbe cercare le div con className: "result", per ogni controllo se il suo div .description contiene la parola "adozione", e se lo fa, fare clic sul div .link. In altre parole, se lo .description non include quella parola, il bot passa al successivo .result.

Questo è quello che ho finora, che scatta appena il primo risultato:

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 

risposta

1

non lo faccio il codice in Ruby, ma in un modo che si possa fare in Python è:

driver.find_elements 

avviso come elementi è plurale, vorrei prendere tutti i link e metterli in un array come.

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

Quindi ottenere tutte le descrizioni allo stesso modo. Esegui un ciclo for per ogni elemento di descrizione, se la descrizione contiene la parola "Adozione" all'interno di tale sito.

ad esempio:

se la descrizione [6] ha la parola 'adozione trovare la href string [6] e passare a href [6].

Spero che abbia senso!

6

È possibile ottenere l'elenco di elementi che contiene "adotta" e "Adotta" da XPath utilizzando contains(), quindi utilizzare l'operatore di unione (|) ai risultati dell'unione di "adottare" e "Adottare". Vedere il codice riportato di seguito:

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 
2

Il modello per gestire ogni iterazione sarà determinato dal tipo di azione eseguita su ciascun elemento. Se l'azione è un clic, non è possibile elencare tutti i collegamenti per fare clic su ognuno di essi poiché il primo clic caricherà una nuova pagina, rendendo obsoleta la lista degli elementi. Quindi Se si desidera cliccare su ogni link, quindi un modo è quello di utilizzare un XPath che contiene la posizione del collegamento per ogni iterazione:

# 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 

Ecco un esempio che fa clic su ogni link da una pagina dei risultati:

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