我如何使用Ruby检查URL是否存在?
例如,对于URL
https://google.com
Run Code Online (Sandbox Code Playgroud)
结果应该是真实的,但对于URL
https://no.such.domain
Run Code Online (Sandbox Code Playgroud)
要么
https://stackoverflow.com/no/such/path
Run Code Online (Sandbox Code Playgroud)
结果应该是假的
Sim*_*tti 66
使用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)
Run Code Online (Sandbox Code Playgroud)
此时res是包含请求结果的Net :: HTTPResponse对象.然后,您可以检查响应代码:
do_something_with_it(url) if res.code == "200"
Run Code Online (Sandbox Code Playgroud)
注意:要检查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)
Run Code Online (Sandbox Code Playgroud)
fot*_*nus 53
对于迟到的回复对不起,但我认为这是一个更好的答案.
有三种方法可以看待这个问题:
虽然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
Run Code Online (Sandbox Code Playgroud)
但是,大多数时候我们不想看看URL是否存在,但是我们是否可以访问它.幸运的是,查看HTTP状态代码系列,即4xx系列客户端错误的状态(因此,您身边的错误,这意味着您没有正确请求页面,没有权限或任何权限).检查是否可以访问此页面时,这是一个很好的错误.来自维基:
4xx类状态代码适用于客户端似乎有错误的情况.除了在响应HEAD请求时,服务器应该包含一个实体,其中包含错误情况的解释,以及它是临时或永久条件.这些状态代码适用于任何请求方法.用户代理应向用户显示任何包含的实体.
因此,以下代码确保URL存在,您可以访问它:
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
Run Code Online (Sandbox Code Playgroud)
就像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
Run Code Online (Sandbox Code Playgroud)
Tur*_*adg 26
Net::HTTP但是如果你能在stdlib之外工作,法拉第会更好.
Faraday.head(the_url).status == 200
Run Code Online (Sandbox Code Playgroud)
(200是成功代码,假设你的意思是"存在".)
| 归档时间: |
|
| 查看次数: |
32883 次 |
| 最近记录: |