2011-09-15 75 views
9

我有一個機械化功能來將我註銷到某個站點,但在非常罕見的情況下,它使我時間流逝。該功能涉及到特定頁面,然後單擊註銷按鈕。偶爾,機械化會在進入註銷頁面或單擊註銷按鈕時崩潰,導致超時。所以我進行了一次小小的救援,看起來像第一段代碼下面看到的那樣工作。用紅寶石機械化捕捉超時錯誤

def logmeout(agent) 
    page = agent.get('http://www.example.com/') 
    agent.click(page.link_with(:text => /Log Out/i)) 
end  

Logmeout救援:

def logmeout(agent) 
    begin 
    page = agent.get('http://www.example.com/') 
    agent.click(page.link_with(:text => /Log Out/i)) 
    rescue Timeout::Error 
    puts "Timeout!" 
    retry 
    end 
end 

假設我理解正確的搶救,它會做這兩個動作上,即使只是點擊超時,所以在努力提高效率,我在想,如果我可以在這種情況下使用一個proc並將其傳遞給一個代碼塊。請問像這樣的工作:

def trythreetimes 
    tries = 0 
    begin 
    yield 
    rescue 
    tries += 1 
    puts "Trying again!" 
    retry if tries <= 3 
    end 
end 

def logmeout(agent) 
    trythreetimes {page = agent.get('http://www.example.com/')} 
    trythreetimes {agent.click(page.link_with(:text => /Log Out/i))} 
end 

注意,在我的trythreetimes功能我把它作爲一般的救援所以功能會更重用。

非常感謝任何人可以提供的幫助,我意識到這裏有幾個不同的問題,但他們都是我努力學習的東西!

回答

9

而不是在某些機械化請求上重試一些超時我認爲您最好將Mechanize::HTTP::Agent::read_timeout屬性設置爲合理的秒數,如2或5,無論如何防止此請求超時錯誤。

然後,您的註銷過程似乎只需要訪問簡單的HTTP GET請求。我的意思是沒有填寫表格,所以沒有HTTP POST請求。 因此,如果我是你,我會優先檢查頁面源代碼(Ctrl + U與Firefox或Chrome),以確定您的鏈接到達agent.click(page.link_with(:text => /Log Out/i)) 它應該更快,因爲這些類型的頁面通常是空白的機械化不需要在內存中加載完整的html網頁。

下面是代碼我寧願使用:

def logmeout(agent) 
    begin 
    agent.read_timeout=2 #set the agent time out 
    page = agent.get('http://www.example.com/logout_url.php') 
    agent.history.pop() #delete this request in the history 
    rescue Timeout::Error 
    puts "Timeout!" 
    puts "read_timeout attribute is set to #{agent.read_timeout}s" if !agent.read_timeout.nil? 
    #retry  #retry is no more needed 
    end 
end 

但你可以用你的重試功能太:

def trythreetimes 
    tries = 0 
    begin 
    yield 
    rescue Exception => e 
    tries += 1 
    puts "Error: #{e.message}" 
    puts "Trying again!" if tries <= 3 
    retry if tries <= 3 
    puts "No more attempt!" 
    end 
end 

def logmeout(agent) 
    trythreetimes do 
    agent.read_timeout=2 #set the agent time out 
    page = agent.get('http://www.example.com/logout_url.php') 
    agent.history.pop()  #delete this request in the history 
    end 
end 

希望它能幫助! ;-)

+0

感謝您的答案!您的首選代碼假設您通過源代碼找到了正確的鏈接? – Sean

+0

好吧,在HTML源代碼中找到一個鏈接並不是很難。由於需要時間和記憶,我更喜歡這個解決方案。但您可以使用您的解決方案與['read_timeout'](http://mechanize.rubyforge.org/Mechanize/HTTP/Agent.html#read_timeout=)集合。如果您將它用於多個域,這是一個好主意。只需編輯我的第二個代碼,然後將其更改爲訪問主頁並點擊鏈接,如果您願意的話。 – cz3ch

+0

對不起,我其實沒有回答你的問題。是的,假設您通過源代碼找到了正確的鏈接... – cz3ch

0

使用機械化1.0.0我從一個不同的錯誤來源得到了這個問題。

在我的情況下,我被代理和SSL封鎖。這對我有效:

ag = Mechanize.new 
ag.set_proxy('yourproxy', yourport) 
ag.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
ag.get(url)