Проверить допустимое доменное имя в строке?

Я использую python и хотел бы, чтобы простой API или регулярное выражение проверяли действительность доменного имени. Под действительностью я подразумеваю синтаксическую действительность, а не от того, действительно ли доменное имя существует в Интернете или нет.


person demos    schedule 24.05.2010    source источник
comment
Кажется, это уже обсуждалось ЗДЕСЬ.   -  person Incognito    schedule 24.05.2010
comment
По какой причине? Если это, скажем, электронная почта, реальную достоверность следует проверять, выполняя DNS-запрос для записи MX, а не с помощью регулярного выражения.   -  person Kimvais    schedule 24.05.2010
comment
Неа. Нет никакой пользы от поиска известных недопустимых имен, это просто пустая трата времени и ресурсов. Также вам не нужна запись MX для доставки электронной почты, достаточно записи A.   -  person Synchro    schedule 22.03.2012


Ответы (5)


Любое доменное имя (синтаксически) допустимо, если оно представляет собой список идентификаторов, разделенных точками, каждый из которых не длиннее 63 символов и состоит из букв, цифр и дефисов (без подчеркивания).

So:

r'[a-zA-Z\d-]{,63}(\.[a-zA-Z\d-]{,63})*'

было бы началом. Конечно, в наши дни могут быть разрешены некоторые символы, отличные от Ascii (совсем недавняя разработка), которые сильно меняют параметры - вам нужно иметь дело с этим?

person Alex Martelli    schedule 24.05.2010
comment
может ли идентификатор начинаться/заканчиваться дефисом? - person Amarghosh; 24.05.2010
comment
Спасибо! Нет, мне не нужна базовая проверка работоспособности, чтобы убедиться, что он не содержит символов из черного списка, таких как ' ! и Т. Д. - person demos; 24.05.2010
comment
Алекс, я знаю, что вы гуру appengine, пожалуйста, помогите мне с этим: stackoverflow.com/questions/2894808/ Заранее спасибо! - person demos; 24.05.2010
comment
@Amarghosh, в соответствии с RFC 1035, да: но в RFC также говорится, что при назначении доменного имени для объекта осмотрительный пользователь выберет более разумное имя (и, в частности, имеет каждый идентификатор, который он называет «меткой», начинаться с буквы, а все доменное имя ограничено 255 байтами). Будьте консервативны в том, что вы создаете, и либеральны в том, что вы принимаете!-) Поскольку RE, несомненно, имеет отношение к принятию, лучше быть либеральным. - person Alex Martelli; 24.05.2010
comment
@demos, я вижу, ты получил хороший ответ на этот другой вопрос (к тому времени, когда ты его задал, я уже спал ;-). - person Alex Martelli; 24.05.2010
comment
@alex да :) У меня есть еще 2 для вас: stackoverflow.com/questions/2906908/ stackoverflow.com/questions/2906746/ Спасибо! - person demos; 25.05.2010
comment
У вас есть два совершенно правильных ответа и на эти два вопроса (хотя они вам явно не нравятся, я не могу ничего добавить к этим ответам). - person Alex Martelli; 26.05.2010
comment
! не обязательно "черный список". RFC2872 говорит, что метки, которые не используются в качестве имен хостов (т. е. которые не сопоставляются с IP-адресами, например, в записях TXT или SRV), могут содержать любые печатные символы ASCII, поэтому _,;:'!@£~$ и друзья — все для включения. Этот документ хорош: domainkeys.sourceforge.net/underscore.html - person Synchro; 22.03.2012
comment
@Synchro - ваша точка зрения верна, но действительно ли она применима к этому вопросу? По-прежнему кажется, что действительное доменное имя не допускает никаких символов, кроме символов «LDH» [ Система доменных имен — Википедия]. - person Kenny Evitt; 03.08.2012
comment
В вопросе не указан контекст, поэтому я думаю, что включать его неразумно - я довольно часто использую имена, отличные от LDH, для поиска ключей DKIM, которые используют такие имена, как blah._domainkey.example.com. - person Synchro; 03.09.2012
comment
Это очень хорошее универсальное регулярное выражение, но следует отметить, что доменное имя не может начинаться с дефиса. - person Neil C. Obremski; 16.01.2015

r'^(?=.{4,255}$)([a-zA-Z0-9][a-zA-Z0-9-]{,61}[a-zA-Z0-9]\.)+[a-zA-Z0-9]{2,5}$'
  • Lookahead гарантирует, что он имеет минимум 4 (a.in) и максимум 255 символов.
  • Одна или несколько меток (разделенных точками) длиной от 1 до 63, начинающихся и заканчивающихся буквенно-цифровыми символами и содержащих буквенно-цифровые символы и дефисы в середине.
  • За которым следует доменное имя верхнего уровня (максимальная длина которого составляет 5 для музея)
person Amarghosh    schedule 24.05.2010
comment
Это не может хранить punycode. Самый короткий кириллический двухбуквенный домен верхнего уровня состоит из 6 букв в punycode. - person kaleissin; 21.03.2013
comment
музей состоит из 6 символов, а не из 5. - person Jonathan Tran; 29.10.2013
comment
Плохая идея жестко запрограммировать ожидаемую длину TLD, особенно теперь, когда появляются IDN TLD, которые закодированы и, следовательно, выходят намного длиннее 5. - person Neil C. Obremski; 16.01.2015
comment
@Amarghosh проверяет 6 символов или 5, потому что ограничение составляет 6 LTD. - person EminezArtus; 17.11.2016

Обратите внимание: несмотря на то, что с регулярными выражениями можно что-то делать, наиболее надежный способ проверки действительных доменных имен — это попытаться разрешить имя (с помощью socket.getaddrinfo):

from socket import getaddrinfo

result = getaddrinfo("www.google.com", None)
print result[0][4]

Обратите внимание, что технически это может оставить вас открытыми для DoS (если кто-то отправит тысячи недействительных доменных имен, может потребоваться некоторое время для разрешения недействительных имен), но вы можете просто ограничить количество тех, кто пытается это сделать.

Преимущество этого в том, что он поймает «hotmail.con» как недействительный (вместо, скажем, «hotmail.com»), тогда как регулярное выражение скажет, что «hotmail.con» действителен.

person Dean Harding    schedule 24.05.2010
comment
Это действительно отдельная проблема и не очень хороший ответ на вопрос. Учитывая, что DNS использовался для эксплойтов в прошлом, проверка того, что строка хотя бы в некоторой степени действительна, перед ее использованием имеет смысл, плюс это на порядки быстрее, чем поиск DNS. Это похоже на запуск кода, чтобы проверить, не является ли он вредоносным! - person Synchro; 22.03.2012
comment
Это нельзя использовать для проверки доменных имен, которые собираются создать, только для уже существующих. - person nerdoc; 23.07.2015
comment
@MichaelSmith, если вам все еще интересно почти год спустя, это потому, что вы не можете выполнить поиск DNS по такому URL-адресу - DNS предназначен только для доменного имени, поэтому его сбивают с толку дополнительные протоколы. - person Xyon; 16.08.2017

Я использовал это:

(r'(\.|\/)(([A-Za-z\d]+|[A-Za-z\d][-])+[A-Za-z\d]+){1,63}\.([A-Za-z]{2,3}\.[A-Za-z]{2}|[A-Za-z]{2,6})')

чтобы убедиться, что он следует либо после точки (www.), либо / (http://), а тире появляется только внутри имени, а также для соответствия суффиксам, таким как gov.uk.

person michalu    schedule 10.11.2013

На данный момент все ответы довольно устарели со спецификацией. Я считаю, что приведенное ниже будет правильно соответствовать текущей спецификации:

r'^(?=.{1,253}$)(?!.*\.\..*)(?!\..*)([a-zA-Z0-9-]{,63}\.){,127}[a-zA-Z0-9-]{1,63}$'
person glustin    schedule 12.12.2017
comment
спецификация ref - person Efren; 31.07.2020