如何檢查使用Ruby的URL是否存在?檢查Ruby中是否存在URL
例如,對於URL
https://google.com
結果應該是truthy,但對於網址
https://no.such.domain
或
https://stackoverflow.com/no/such/path
結果應該是falsey
如何檢查使用Ruby的URL是否存在?檢查Ruby中是否存在URL
例如,對於URL
https://google.com
結果應該是truthy,但對於網址
https://no.such.domain
或
https://stackoverflow.com/no/such/path
結果應該是falsey
使用Net::HTTP庫。
require "net/http"
url = URI.parse("http://www.google.com/")
req = Net::HTTP.new(url.host, url.port)
res = req.request_head(url.path)
此時res
是包含請求的結果的Net::HTTPResponse對象。然後,您可以檢查響應代碼:
do_something_with_it(url) if res.code == "200"
注意:要檢查https
基於URL,use_ssl
屬性應該是true
爲:
require "net/http"
url = URI.parse("https://www.google.com/")
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = true
res = req.request_head(url.path)
重定向怎麼辦? 302 http代碼 – 2014-03-23 19:07:44
在生產中,對於每一個URL,這是返回我200代碼.. 我已經解析了這個URL,並給了我200 OK ...但是哪個是錯的......這裏有什麼問題?任何想法? 注意:這在Local Env中工作正常。 – 2016-10-06 11:34:40
你應該看看這篇文章:
Simone的回答是對我很有幫助。
下面是根據URL有效性返回true/false一個版本,它處理重定向:
require 'net/http'
require 'set'
def working_url?(url, max_redirects=6)
response = nil
seen = Set.new
loop do
url = URI.parse(url)
break if seen.include? url.to_s
break if seen.size > max_redirects
seen.add(url.to_s)
response = Net::HTTP.new(url.host, url.port).request_head(url.path)
if response.kind_of?(Net::HTTPRedirection)
url = response['location']
else
break
end
end
response.kind_of?(Net::HTTPSuccess) && url.to_s
end
如果服務器不支持HEAD請求,該怎麼辦? – 2017-11-12 16:04:46
對不起,這個後期的答覆,但我認爲這deservers一個更好的答案。
有三種方式來看待這個問題:
雖然200
意味着服務器回答該URL(因此該URL存在),但回答其他狀態碼並不意味着該URL不存在。例如,回答302 - redirected
意味着該URL存在並正在重定向到另一個URL。瀏覽時,302
多次表現與最終用戶的200
相同。如果URL存在,可以返回的其他狀態代碼是500 - internal server error
。畢竟,如果URL不存在,那麼應用程序服務器如何處理您的請求,而僅返回404 - not found
?
所以實際上只有一種情況下,當一個URL不存在時:當服務器不存在或當服務器存在但無法找到給定的URL路徑不存在。 因此,檢查URL是否存在的唯一方法是檢查服務器是否應答並且返回代碼不是404.以下代碼就是這樣做的。
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
res.code != "404" # false if returns 404 - not found
rescue Errno::ENOENT
false # false if can't find the server
end
然而,大部分的時間我們都沒有興趣看有沒有存在的網址,但如果能訪問它。幸運的是,看到HTTP status codes系列,即4xx
系列,其中聲明客戶端錯誤(因此,您身邊的錯誤,這意味着您沒有正確請求頁面,沒有任何權限)。這是一個很好的錯誤來檢查您是否可以訪問此頁面。從維基:
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents should display any included entity to the user.
所以下面的代碼確認網址存在,並且您可以訪問它:
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
if res.kind_of?(Net::HTTPRedirection)
url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL
else
res.code[0] != "4" #false if http code starts with 4 - error on your side.
end
rescue Errno::ENOENT
false #false if can't find the server
end
就像4xx
家族檢查您是否可以訪問URL一樣,5xx
系列會檢查服務器是否有任何問題回答您的請求。大多數時候這個家族的錯誤是服務器本身的問題,希望他們正在努力解決它。如果您需要能夠訪問該頁面並現在得到正確的答案,您應該確保答案不是來自4xx
或5xx
系列,並且如果您被重定向,則重定向頁面可以正確回答。如此多的相似(2),你可以簡單地使用下面的代碼:
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
if res.kind_of?(Net::HTTPRedirection)
url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL
else
! %W(4 5).include?(res.code[0]) # Not from 4xx or 5xx families
end
rescue Errno::ENOENT
false #false if can't find the server
end
如果你用https-urls做這個,你可能會得到一個'Net :: HTTPBadResponse:錯誤的狀態行'錯誤。這是因爲你必須告訴Net:HTTP來使用ssl。爲了使它適用於https,也可以使用'req.use_ssl =(url。方案=='https')'調用'request_head'之前 – 2014-01-06 08:29:13
@YoLudke感謝您的貢獻 – fotanus 2014-01-06 10:23:57
另一件事:如果您請求(或重定向轉到)'http://www.example.com'(不帶尾部' /'),那麼你會得到一個'ArgumentError:HTTP請求路徑爲空'。這可以通過將'res = req.request_head(url.path)'行改爲'path = url.path if url.path.present?'和'req.request_head(path ||'/')' – 2014-01-08 08:49:04
問題是不夠好,符合我的谷歌搜索,答案是有價值 – kranzky 2017-01-27 04:13:00
我同意。這個問題很有用。 – 2017-03-24 01:43:40
我認爲這是一個有用的答案很好的問題。它被關閉的原因(「必須證明最低限度的理解」)在SO上不再有效。我編輯了這個問題來添加一些例子。那麼,我認爲這個問題現在可以重新開放了。 – 2017-07-08 16:45:21