您将如何解析 Ruby 中的 url 以获取主域?
Posted
技术标签:
【中文标题】您将如何解析 Ruby 中的 url 以获取主域?【英文标题】:How would you parse a url in Ruby to get the main domain? 【发布时间】:2011-10-04 04:36:21 【问题描述】:我希望能够使用 Ruby 解析任何 URL,以获取没有 www
的域的主要部分(只是 example.com
)
【问题讨论】:
在匹配最终实体服务器证书时,Ruby 无法在所有条件下正确处理主机名匹配。我知道一些意想不到的荒谬结果。 【参考方案1】:请注意没有算法方法可以找到可以为特定***域注册域的***别(每个注册机构的政策不同),唯一的方法是创建所有***域的列表以及可以注册域的级别。
这就是Public Suffix List 存在的原因。
我是PublicSuffix 的作者,这是一个将域分解为不同部分的 Ruby 库。
这是一个例子
require 'uri/http'
uri = URI.parse("http://toolbar.google.com")
domain = PublicSuffix.parse(uri.host)
# => "toolbar.google.com"
domain.domain
# => "google.com"
uri = URI.parse("http://www.google.co.uk")
domain = PublicSuffix.parse(uri.host)
# => "www.google.co.uk"
domain.domain
# => "google.co.uk"
【讨论】:
最后一个domain.domain #=> "google.com"
是错误还是我不明白什么??
不,这不是一个错误。第一个domain
是一个变量,第二个是方法调用。该变量可以随心所欲地调用。
“这就是公共后缀列表存在的原因......” - 我不相信“主”域和 PSL 中的条目是一回事。 PSL 包括 gTLD、ccTLD 和 cookie 路径。确定“主”域不需要 cookie 路径,它可能会导致错误的结果。
@SimoneCarletti 我最初的评论是不久前的,但我的意思是在最后一个例子中.co.uk
,突然变成.com
。
我会将domain.domain
重命名为domain.name
【参考方案2】:
这应该适用于几乎任何 URL:
# URL always gets parsed twice
def get_host_without_www(url)
url = "http://#url" if URI.parse(url).scheme.nil?
host = URI.parse(url).host.downcase
host.start_with?('www.') ? host[4..-1] : host
end
或者:
# Only parses twice if url doesn't start with a scheme
def get_host_without_www(url)
uri = URI.parse(url)
uri = URI.parse("http://#url") if uri.scheme.nil?
host = uri.host.downcase
host.start_with?('www.') ? host[4..-1] : host
end
您可能需要require 'uri'
。
【讨论】:
如果url
只是www.example.com
这可能行不通,URI 对没有方案的 URI 反应不佳。
您可以通过在u = URI.parse(url)
之后检查u.scheme
然后在必要时添加一个方案并重新解析来解决这个问题。
我认为这些变得太复杂了。这应该可以工作:URI('http://www.example.com').host.match(/[^\.]+\.\w+$/).to_s
.
@Chip 嘿,你的正则表达式无法检查ccTLD
如果URI('http://www.example.co.kr').host.match(/[^\.]+\.\w+$/).to_s
编码,则输出=> "co.kr"
【参考方案3】:
简短说明:为了克服 Mischas 第二个示例中对 url 的第二次解析,您可以进行字符串比较而不是 URI.parse。
# Only parses once
def get_host_without_www(url)
url = "http://#url" unless url.start_with?('http')
uri = URI.parse(url)
host = uri.host.downcase
host.start_with?('www.') ? host[4..-1] : host
end
这种方法的缺点是,它将 url 限制为基于 http(s) 的 url,这是广泛的标准。但是,如果您将使用它更通用(例如用于 ftp 链接),则必须相应地进行调整。
【讨论】:
【参考方案4】:Addressable可能是2018年的正确答案,尤其是uses the PublicSuffix gem to parse domains。
但是,我需要在多个地方,从各种数据源进行这种解析,发现重复使用有点冗长。所以我围绕它创建了一个包装器,Adomain:
require 'adomain'
Adomain["https://toolbar.google.com"]
# => "toolbar.google.com"
Adomain["https://www.google.com"]
# => "google.com"
Adomain["***.com"]
# => "***.com"
我希望这对其他人有所帮助。
【讨论】:
【参考方案5】:这是一个更适合 .co.uk 和 .com.fr 类型的域
domain = uri.host[/[^.\s\/]+\.([a-z]3,|([a-z]2|com)\.[a-z]2)$/]
【讨论】:
在这个上返回 nil:moebel-turflon.de/karriere/jobs/136【参考方案6】:如果 URL 的格式为 http://www.google.com
,那么您可以执行以下操作:
a = 'http://www.google.com'
puts a.split(/\./)[1] + '.' + a.split(/\./)[2]
或者
a =~ /http:\/\/www\.(.*?)$/
puts $1
【讨论】:
绝对不是——这真的取决于你的输入——你一次只接收一个网址作为输入吗?网址有相对路径吗?他们总是带有www
作为子域吗?他们总是有一个子域吗?它们都是http
网址还是您获得带有https
、ftp
等的网址?还有更多问题可以问 - 这只是为了让你开始:)
这不适用于英国域名co.uk
例如【参考方案7】:
你可以写这个方法:
require 'URI'
def domain_name(url, arg=:with_dot_principal=>false)
arg[:with_dot_principal] ? URI(url).hostname.split('.').last(2).join('.') : URI(url).hostname.split('.').last(2).first
end
并使用:
domain_name("https://www.google.com/?gws_rd=ssl&safe=active&ssui=on")
# => "google"
domain_name("http://google.com", with_dot_principal: true)
# => "google.com"
【讨论】:
这不适用于 ccTLD,例如domain_name("https://www.google.co.uk/?gws_rd=ssl&safe=active&ssui=on") #=> "co"
你是对的,这仅适用于问题的具体示例,也就是说,只是一个示例,在过去的几年里,我假装开发人员应该理解并采取相应的行动。以上是关于您将如何解析 Ruby 中的 url 以获取主域?的主要内容,如果未能解决你的问题,请参考以下文章
如何解析 Postgresql JDBC url 以获取主机名、端口和 db_name