我需要在ruby中使用open-uri打开一些网页,然后使用Nokogori解析这些页面的内容。 我刚刚做了:
require 'open-uri'
content_file = open(user_input_url)
这适用于:http://www.google.co.in
和http://google.co.in
,但在用户提供www.google.co.in
或google.co.in
等输入时失败。
我可以对此类输入执行一项操作,我可以附加http://
和https://
并返回打开的页面内容。但这对我来说似乎是个大黑客。
有没有更好的方法在ruby中实现这一点(即将这些user_input转换为有效的open_uri url)。
答案 0 :(得分:7)
uri = URI("www.google.com")
if uri.instance_of?(URI::Generic)
uri = URI::HTTP.build({:host => uri.to_s})
end
content_file = open(uri)
还有其他方法可以参见参考:http://www.ruby-doc.org/stdlib-2.0.0/libdoc/uri/rdoc/URI/HTTP.html
答案 1 :(得分:3)
如果不存在,则预先添加该方案,然后使用URI
来检查URL有效性:
require 'uri'
url = 'www.google.com/a/b?c=d#e'
url.prepend "http://" unless url.start_with?('http://', 'https://')
url = URI(url) # it will raise error if the url is not valid
open url
不幸的是,你所需要的“面向对象”版本更冗长,甚至更具黑客性:
require 'uri'
case url = URI.parse 'www.google.com/a/b?c=d#e'
when URI::HTTP, URI::HTTPS
# no-op
when URI::Generic
# We need to split u.path at the first '/', since URI::Generic interprets
# 'www.google.com/a/b' as a single path
host, path = url.path.split '/', 2
url = URI::HTTP.build host: host ,
path: "/#{path}" ,
query: url.query ,
fragment: url.fragment
else
raise "unsupported url class (#{url.class}) for #{url}"
end
open url
如果您接受建议,请不要过分夸大其词:我经常遇到这个问题而且我很确定没有“抛光”的方法来做这件事
答案 2 :(得分:1)
你需要在网址前加上http
,没有明确的方案,uri可能是任何东西,例如:本地文件。 uri不一定是http url。
您可以使用URI
类或使用正则表达式来检查:
user_input_url = URI.parse(user_input_url).scheme ?
user_input_url :
"http://#{user_input_url}"
user_input_url = user_input_url =~ /https?:\/\// ?
user_input_url :
"http://#{user_input_url}"
答案 3 :(得分:0)
def instance_to_hash(instance)
hash = {}
instance.instance_variables.each {|var| hash[var[1..-1].to_sym] = instance.instance_variable_get(var) }
hash
end
def url_compile(url)
# if url without 'http://', 'https://', '//' at start of string
# then prepend '//'
url.prepend '//' unless url.start_with?('http://', 'https://', '//')
uri = URI(url)
if uri.instance_of?(URI::Generic) # if scheme nil then assume it HTTPS
uri = URI::HTTPS.build(instance_to_hash(uri))
end
uri
end