2011-04-03 196 views

回答

1

您將不得不關注重定向。我認爲,這將有助於:

http://shadow-file.blogspot.com/2009/03/handling-http-redirection-in-ruby.html

+1

技術上不正確。你不需要「關注」重定向,你只需要讀取發送來重定向的位置標題,就像在MladenJablanović的回答中一樣。 – jemminger 2011-04-03 21:15:41

+0

你是對的,我沒有正確說明:) – Spyros 2011-04-03 22:27:52

+1

有可能重定向被重定向。除非底層代碼自動處理它,它不會使用Net :: HTTP,否則必須遵循重定向,直到您確定重定向太深,或者最終在最終URL處終止。鏈接到的特定頁面比Net :: HTTP文檔中的示例更加複雜。 – 2011-04-03 23:14:53

23
require 'net/http' 
require 'uri' 

Net::HTTP.get_response(URI.parse('http://t.co/yjgxz5Y'))['location'] 
# => "http://nickstraffictricks.com/4856_how-to-rank-1-in-google/" 
+2

根據文檔,Net :: HTTP不會執行遞歸重定向,如果重定向被重定向,這是必需的。這看起來像只能處理第一個。 – 2011-04-03 23:17:02

+1

是的。你需要一個循環。但無論如何,這是你如何遵循Ruby中的重定向,我相信這回答了這個問題。 – 2011-04-04 06:32:06

8

我用open-uri對於這一點,因爲它的簡單好用。它將檢索頁面,也將遵循多重定向:

require 'open-uri' 

final_uri = '' 
open('http://t.co/yjgxz5Y') do |h| 
    final_uri = h.base_uri 
end 
final_uri # => #<URI::HTTP:0x00000100851050 URL:http://nickstraffictricks.com/4856_how-to-rank-1-in-google/> 

該文檔顯示一個很好的例子使用較低級別的Net::HTTP處理重定向。

require 'net/http' 
require 'uri' 

def fetch(uri_str, limit = 10) 
    # You should choose better exception. 
    raise ArgumentError, 'HTTP redirect too deep' if limit == 0 

    response = Net::HTTP.get_response(URI.parse(uri_str)) 
    case response 
    when Net::HTTPSuccess  then response 
    when Net::HTTPRedirection then fetch(response['location'], limit - 1) 
    else 
    response.error! 
    end 
end 

puts fetch('http://www.ruby-lang.org') 

當然,如果頁面沒有使用HTTP重定向,這一切都會崩潰。很多網站使用元重定向,您必須通過從元標記中檢索URL來處理這些重定向,但這是一個不同的問題。

+0

謝謝!非常有幫助..做h.base_uri.to_s將呈現目標網址。 – KG2289 2013-01-24 20:06:51

+0

我認爲你可以跳過塊的使用,只需調用'open(url).base_uri' – lulalala 2013-11-27 04:14:57

+0

'Net :: HTTP'版本應該是可接受的答案,因爲它處理SSL以及遞歸重定向(大多數示例似乎只處理一個或另一個)。做得好! – 2015-04-04 03:43:39

3

爲了解決重定向問題,您應該使用HEAD請求來避免下載整個響應主體(想象一下將一個URL解析爲音頻或視頻文件)。使用法拉第寶石

工作實施例:

require 'faraday' 
require 'faraday_middleware' 

def resolve_redirects(url) 
    response = fetch_response(url, method: :head) 
    if response 
     return response.to_hash[:url].to_s 
    else 
     return nil 
    end 
end 

def fetch_response(url, method: :get) 
    conn = Faraday.new do |b| 
     b.use FaradayMiddleware::FollowRedirects; 
     b.adapter :net_http 
    end 
    return conn.send method, url 
rescue Faraday::Error, Faraday::Error::ConnectionFailed => e 
    return nil 
end 

puts resolve_redirects("http://cre.fm/feed/m4a") # http://feeds.feedburner.com/cre-podcast