7

我正在遍历一系列 URL 并想要清理它们。我有以下代码:

# Parse url to remove http, path and check format
o_url = URI.parse(node.attributes['href'])

# Remove www
new_url = o_url.host.gsub('www.', '').strip

如何扩展它以删除某些 URL 中存在的子域?

4

8 回答 8

30

我刚刚编写了一个名为 Domainatrix 的库来执行此操作。你可以在这里找到它:http: //github.com/pauldix/domainatrix

require 'rubygems'
require 'domainatrix'

url = Domainatrix.parse("http://www.pauldix.net")
url.public_suffix       # => "net"
url.domain    # => "pauldix"
url.canonical # => "net.pauldix"

url = Domainatrix.parse("http://foo.bar.pauldix.co.uk/asdf.html?q=arg")
url.public_suffix       # => "co.uk"
url.domain    # => "pauldix"
url.subdomain # => "foo.bar"
url.path      # => "/asdf.html?q=arg"
url.canonical # => "uk.co.pauldix.bar.foo/asdf.html?q=arg"
于 2009-12-11T21:05:54.680 回答
7

这是一个棘手的问题。一些顶级域不接受二级注册。

比较example.comexample.co.uk。如果您只是简单地剥离除最后两个域之外的所有内容,那么您最终会得到example.com, 和co.uk,这绝不是意图。

Firefox 通过有效的顶级域过滤解决了这个问题,他们维护了所有这些域的列表。更多信息请访问publicsuffix.org

您可以使用此列表过滤除有效 TLD 旁边的域之外的所有内容。我不知道有任何 Ruby 库可以做到这一点,但发布一个是个好主意!

更新:有C、Perl 和 PHP 库可以做到这一点。给定 C 版本,您可以创建一个 Ruby 扩展。或者,您可以将代码移植到 Ruby。

于 2009-06-11T19:46:48.893 回答
7

对于后代,这是 2014 年 10 月的更新:

我正在寻找一个更新的依赖项来依赖并找到了 public_suffix gem ( RubyGems ) ( GitHub )。它正在积极维护,并通过维护已知公共后缀列表来处理所有顶级域和嵌套子域问题。

结合 URI.parse 来剥离协议和路径,效果非常好:

❯❯❯ 2.1.2 ❯ PublicSuffix.parse(URI.parse('https://subdomain.google.co.uk/path/on/path').host).domain
=> "google.co.uk"
于 2014-10-21T01:59:35.257 回答
3

您在这里需要的正则表达式可能有点棘手,因为主机名可能非常复杂——您可以有多个子域(即 foo.bar.baz.com),或者顶级域 (TLD) 可以有多个部分(即 www.baz.co.uk)。

准备好复杂的正则表达式了吗?:)

re = /^(?:(?>[a-z0-9-]*\.)+?|)([a-z0-9-]+\.(?>[a-z]*(?>\.[a-z]{2})?))$/i
new_url = o_url.host.gsub(re, '\1').strip

让我们把它分成两个部分。^(?:(?>[a-z0-9-]*\.)+?|)将通过匹配一组或多组字符后跟一个点来收集子域(贪婪地,以便在此处匹配所有子域)。如果没有子域(如 foo.com),则需要空交替。([a-z0-9-]+\.(?>[a-z]*(?>\.[a-z]{2})?))$将收集实际的主机名和 TLD。它允许使用单部分 TLD(如 .info、.com 或 .museum)或两部分 TLD,其中第二部分是两个字符(如 .oh.us 或 .org.uk)。

我在以下样本上测试了这个表达式:

foo.com => foo.com
www.foo.com => foo.com
bar.foo.com => foo.com
www.foo.ca => foo.ca
www.foo.co.uk => foo.co.uk
a.b.c.d.e.foo.com => foo.com
a.b.c.d.e.foo.co.uk => foo.co.uk

请注意,此正则表达式不会正确地将具有两个以上“部分”的主机名与 TLD 匹配!

于 2009-06-11T20:46:10.793 回答
2

就像是:

def remove_subdomain(host)
    # Not complete. Add all root domain to regexp
    host.sub(/.*?([^.]+(\.com|\.co\.uk|\.uk|\.nl))$/, "\\1")
end

puts remove_subdomain("www.example.com") # -> example.com
puts remove_subdomain("www.company.co.uk") # -> company.co.uk
puts remove_subdomain("www.sub.domain.nl") # -> domain.nl

您仍然需要添加您认为是根域的所有(根)域。所以“.uk”可能是根域,但您可能希望将主机保留在“.co.uk”部分之前。

于 2009-06-11T19:43:32.363 回答
1

从一般意义上来说,检测 URL 的子域并非易事——如果您只考虑基本的子域,这很容易,但是一旦您进入国际领域,这就变得很棘手。

编辑:考虑像http://mylocalschool.k12.oh.us等的东西。

于 2009-06-11T19:45:27.647 回答
0

为什么不直接去掉 .com 或 .co.uk,然后在 '.' 上拆分?并获得最后一个元素?

some_url.host.sub(/(\.co\.uk|\.[^.]*)$/).split('.')[-1] + $1

不得不说这感觉很hacky。有没有像 .co.uk 这样的其他域名?

于 2014-11-20T15:37:24.560 回答
0

多年来,我在编写各种杂乱无章的爬虫和刮板时为此苦苦挣扎。我最喜欢解决这个问题的 gem 是 Pete Gamache 的 FuzzyUrl:https ://github.com/gamache/fuzzyurl 。它可用于 Ruby、JavaScript 和 Elixir。

于 2017-04-18T09:16:19.953 回答