2010-02-09 78 views
15

我想寫我的第一個Ruby程序,但有問題。代碼必須通過HTTP下載32個MP3文件。它實際上下載了一些,然後超時。Ruby Net :: HTTP超時

我試着設置一個超時時間,但沒有區別。在Windows下運行代碼,Cygwin和Mac OS X具有相同的結果。

這是代碼:

require 'rubygems' 
require 'open-uri' 
require 'nokogiri' 
require 'set' 
require 'net/http' 
require 'uri' 

puts "\n Up and running!\n\n" 

links_set = {} 

pages = ['http://www.vimeo.com/siai/videos/sort:oldest', 
    'http://www.vimeo.com/siai/videos/page:2/sort:oldest', 
    'http://www.vimeo.com/siai/videos/page:3/sort:oldest'] 

pages.each do |page| 
    doc = Nokogiri::HTML(open(page)) 
    doc.search('//*[@href]').each do |m| 
    video_id = m[:href] 
    if video_id.match(/^\/(\d+)$/i) 
    links_set[video_id[/\d+/]] = m.children[0].to_s.split(" at ")[0].split(" -- ")[0] 
    end 
    end 
end 

links = links_set.to_a 

p links 

cookie = '' 
file_name = '' 

open("http://www.tubeminator.com") {|f| 
    cookie = f.meta['set-cookie'].split(';')[0] 
} 

links.each do |link| 
    open("http://www.tubeminator.com/ajax.php?function=downloadvideo&url=http%3A%2F%2Fwww.vimeo.com%2F" + link[0], 
    "Cookie" => cookie) {|f| 
     puts f.read 
    } 

    open("http://www.tubeminator.com/ajax.php?function=convertvideo&start=0&duration=1120&size=0&format=mp3&vq=high&aq=high", 
    "Cookie" => cookie) {|f| 
     file_name = f.read 
    } 
    puts file_name 

    Net::HTTP.start("www.tubeminator.com") { |http| 
    #http.read_timeout = 3600 # 1 hour 
    resp = http.get("/download-video-" + file_name) 
    open(link[1] + ".mp3", "wb") { |file| 
     file.write(resp.body) 
    } 
    } 
end 

puts "\n Yay!!" 

這是個例外:

/Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:140:in `rescue in rbuf_fill': Timeout::Error (Timeout::Error) 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:134:in `rbuf_fill' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:116:in `readuntil' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/protocol.rb:126:in `readline' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:2138:in `read_status_line' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:2127:in `read_new' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:1120:in `transport_request' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:1106:in `request' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:312:in `block in open_http' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/net/http.rb:564:in `start' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:306:in `open_http' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:767:in `buffer_open' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:203:in `block in open_loop' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:201:in `catch' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:201:in `open_loop' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:146:in `open_uri' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:669:in `open' 
from /Users/test/.rvm/rubies/ruby-1.9.2-preview1/lib/ruby/1.9.1/open-uri.rb:33:in `open' 
from test.rb:38:in `block in <main>' 
from test.rb:37:in `each' 
from test.rb:37:in `<main>' 

我也很感激在代碼的其餘部分您的意見。

+0

也許當您爲視頻下載構建網址時會出現問題。選擇有問題的網址並嘗試手動下載。 – Lucas 2010-02-09 13:19:12

+1

嗨盧卡斯:) URL是好的,我可以用瀏覽器下載文件。問題是它下載較大的文件時(超過20MB)超時。 – 2010-02-09 13:22:56

回答

15

您的超時不在您設置超時的代碼中。它在這裏,在您使用開放式的URI:

open("http://www.tubeminator.com/ajax.php?function=downloadvideo&url=http%3A%2F%2Fwww.vimeo.com%2F" + link[0], 

您可以設置讀取超時開放-URI像這樣:

#!/usr/bin/ruby1.9 

require 'open-uri' 

open('http://stackoverflow.com', 'r', :read_timeout=>0.01) do |http| 
    http.read 
end 

# => /usr/lib/ruby/1.9.0/net/protocol.rb:135:in `sysread': \ 
# => execution expired (Timeout::Error) 
# => ... 
# =>   from /tmp/foo.rb:5:in `<main>' 

:read_timeout是新的Ruby 1.9(它不是用Ruby 1.8) 。 0或nil表示「不超時」。

+0

你知道一個Ruby 1.8解決方案嗎? – madh 2010-02-23 00:19:31

+0

@madh,我沒有,但是可以掏出來,例如wget。 – 2010-02-23 14:39:15

+4

您可以設置Net :: HTTP對象的read_timeout和conn_timeout。 – 2010-09-27 16:01:21

20

對於Ruby 1.8,我用它來解決我的超時問題。在我的代碼中擴展Net :: HTTP類,並使用默認參數(包括我自己的read_timeout的初始化)重新初始化,這應該讓我覺得很理智。

require 'net/http' 

# Lengthen timeout in Net::HTTP 
module Net 
    class HTTP 
     alias old_initialize initialize 

     def initialize(*args) 
      old_initialize(*args) 
      @read_timeout = 5*60  # 5 minutes 
     end 
    end 
end 
+3

謝謝你,你就像是在我需要你的時刻從天而降的天使。 – Darren 2012-02-16 18:50:57

+0

@Darren很高興我可以幫忙:-) – 2012-02-22 23:02:07

+0

你把這段代碼放在哪裏? – Nick 2012-07-11 17:04:46