Удалить поддомен из строки в ruby
Я перебираю серию 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?
8 ответов
Я только что написал библиотеку для этого под названием 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"
Для потомков, вот обновление от октября 2014 года:
Я искал более актуальную зависимость, на которую можно было бы положиться, и нашел гем public_suffix ( RubyGems) ( GitHub). Он активно поддерживается и обрабатывает все проблемы домена верхнего уровня и вложенного субдомена, поддерживая список известных общедоступных суффиксов.
В сочетании с URI.parse для разбора протокола и путей он работает очень хорошо:
❯❯❯ 2.1.2 ❯ PublicSuffix.parse(URI.parse('https://subdomain.google.co.uk/path/on/path').host).domain
=> "google.co.uk"
Это сложная проблема. Некоторые домены верхнего уровня не принимают регистрации на втором уровне.
сравнить example.com
а также example.co.uk
, Если вы просто удалите все, кроме двух последних доменов, вы получите example.com
, а также co.uk
, который никогда не может быть намерением.
Firefox решает эту проблему путем фильтрации по эффективному домену верхнего уровня, и они поддерживают список всех этих доменов. Более подробная информация на http://publicsuffix.org/.
Вы можете использовать этот список, чтобы отфильтровать все, кроме домена рядом с действующим TLD. Я не знаю ни одной библиотеки Ruby, которая бы это делала, но было бы неплохо выпустить ее!
Обновление: есть библиотеки C, Perl и PHP, которые делают это. Учитывая версию C, вы можете создать расширение для Ruby. Кроме того, вы можете перенести код на Ruby.
Регулярное выражение, которое вам понадобится, может быть немного сложным, потому что имена хостов могут быть бесконечно сложными - у вас может быть несколько поддоменов (например, 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!
Что-то вроде:
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".
Обнаружение субдомена URL-адреса нетривиально в общем смысле - это легко, если вы просто рассмотрите основные из них, но как только вы попадаете на международную территорию, это становится сложно.
Изменить: рассмотреть такие вещи, как http://mylocalschool.k12.oh.us/ и др.
Почему бы просто не убрать.com или.co.uk, а затем разделить на '.' и получить последний элемент?
some_url.host.sub(/(\.co\.uk|\.[^.]*)$/).split('.')[-1] + $1
Должен сказать, это чувствует себя хакером. Есть ли другие домены, как.co.uk?
За эти годы я много боролся с этим при написании различных и разных сканеров и скребков. Моя любимая жемчужина для решения этой проблемы - FuzzyUrl от Pete Gamache: https://github.com/gamache/fuzzyurl. Он доступен для Ruby, JavaScript и Elixir.