2014-04-07 76 views
3

我對Ruby和Selenium很新。使用Ruby和Selenium Webdriver find_elements根據條件選擇並單擊特定鏈接

我正在嘗試編寫一個腳本來打開網頁(不是我運行的頁面),查看那裏的項目列表,然後單擊符合特定條件的項目的「詳細信息」鏈接。頁面的一個非常精簡的版本是:

<div class="list"> 

<div class="item"> 
    <div class="description">Cat</div> 
    <div class="price">$3.00</div> 
    <div class="detailslink"> 
     <a href="http://a.htm">Details</a> 
    </div> 
</div> 

<div class="item"> 
    <div class="description">Dog</div> 
    <div class="price">$4.00</div> 
    <div class="detailslink"> 
     <a href="http://b.htm">Details</a> 
    </div> 
</div> 

<div class="item"> 
    <div class="description">Cat</div> 
    <div class="price">$4.00</div> 
    <div class="detailslink"> 
     <a href="http://c.htm">Details</a> 
    </div> 
</div> 

<div class="item"> 
    <div class="description">Bird</div> 
    <div class="price">$3.00</div> 
    <div class="detailslink"> 
     <a href="http://d.htm">Details</a> 
    </div> 
</div> 

的我想要做什麼的一個例子是點擊「詳細信息」鏈接,最昂貴的動物是不是狗。我猜測我會創建一個包含find_elements的所有「item」類元素的數組,其中不包含單詞「dog」,找到該數組中最高價格的索引,然後單擊相應的「detailslink 「,但我不知道如何用Ruby寫出來。

理想情況下,如果沒有符合條件的列表項(「列表」div中沒有​​「item」div,或者所有「list」div都包含Cat),它也會每30秒刷新一次。這是我到目前爲止(我知道它是缺少很多!):

require "selenium-webdriver" 
browser = Selenium::WebDriver.for :chrome 
browser.get "http://list.htm" 
for i in 0..1 
    items = browser.find_elements(:class=>"item") 
    #Do testing here. If there are non-cats, get the index of the max. 
     break 
    end 
    sleep(30) 
    browser.get "http://list.htm" 
    redo 
end 
#find the nth element based on the test above 
browser.find_element(:class, "detailslink")[index].click 

任何幫助將不勝感激!

回答

2

我不認爲這是通用的解決方案,但是對於你的具體的例子:

browser = Selenium::WebDriver.for :firefox 
browser.navigate.to 'C:\Scripts\Misc\Programming\Selenium-Webdriver\test.htm' 

# Refresh the page until there is at least 1 dog 
items = browser.find_elements(:class=> 'item') 
dog_items = items.find_all{ |item| item.find_element(:class => 'description').text == 'Dog' } 
while dog_items.length == 0 
    sleep(30) 
    browser.navigate.refresh 
    items = browser.find_elements(:class=> 'item') 
    dog_items = items.find_all{ |item| item.find_element(:class => 'description').text == 'Dog' }  
end 

# Select the dog with the greatest price 
most_expensive = dog_items.sort_by{ |dog| dog.find_element(:class => 'price').text.delete('$').to_f }.last 

# Click the selected dog 
most_expensive.find_element(:css => '.detailslink a').click 
+0

'while..end'是好招..我喜歡它.. –

+0

這完美地工作!非常感謝。 – user3507629

0

我從來沒有真正嘗試過使用Seleniumnokogiri它會是這樣的(我做了更詳細的爲清楚起見,顯然有些方法可以鏈接)

require 'open-uri' 
require 'nokogiri' 
doc = Nokogiri::HTML(open("http://list.htm")) 
items = doc.css(".item") 
non_dog_items = items.reject{|item| item.children.css(".description").text == "Dog"} 
most_expensive_non_dog_item = non_dog_items.max_by{|item| item.children.css(".price").text.gsub("$",'').to_f} 
link_to_most_expensive_non_dog_item = most_expensive_non_dog_item.css(".detailsLink a").attributes["href"].value 
#=> "http://c.htm" 

與此唯一的問題是,如果你的項目2具有相同的價格,以便與回報max_by具有最高的性價比的第一個項目。

你也可以返回所有的項目,如哈希,然後用哈希只處理

require 'open-uri' 
require 'nokogiri' 

doc = Nokogiri::HTML(open('/scripts/test.html')) 
items = doc.css(".item").reject{|item| item.css(".description").text == "Dog"} 
items_hash = items.map do |item| 
     {description: item.css(".description").text, 
     price: item.css(".price").text.gsub("$",'').to_f, 
     link: item.css(".detailsLink a").attributes["href"].value 
     } 
    end 
#=> [{:description=>"Cat", :price=>3.0, :link=>"http://a.htm"},{:description=>"Cat", :price=>4.0, :link=>"http://c.htm"},{:description=>"Bird", :price=>3.0, :link=>"http://d.htm"}] 
相關問題