跟进Regular expression to match hostname or IP Address? 并使用Restrictions on valid host names作为参考,在Python中匹配/验证主机名/ fqdn(完全限定域名)的最可读,最简洁的方法是什么?我已经回答了下面的尝试,欢迎改进。
答案 0 :(得分:44)
import re
def is_valid_hostname(hostname):
if len(hostname) > 255:
return False
if hostname[-1] == ".":
hostname = hostname[:-1] # strip exactly one dot from the right, if present
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
确保每个细分
它还避免了双重否定(not disallowed
),如果hostname
以.
结尾,那也没关系。如果hostname
以多个点结束,它将(并且应该)失败。
答案 1 :(得分:3)
这里有Tim Pietzcker's answer更严格的版本,但有以下改进:
[0-9]
代替\d
)。import re
def is_valid_hostname(hostname):
if hostname[-1] == ".":
# strip exactly one dot from the right, if present
hostname = hostname[:-1]
if len(hostname) > 253:
return False
labels = hostname.split(".")
# the TLD must be not all-numeric
if re.match(r"[0-9]+$", labels[-1]):
return False
allowed = re.compile(r"(?!-)[a-z0-9-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(label) for label in labels)
答案 2 :(得分:3)
每The Old New Thing,DNS名称的最大长度为253个字符。 (一个允许最多255个八位字节,但其中2个由编码消耗。)
import re
def validate_fqdn(dn):
if dn.endswith('.'):
dn = dn[:-1]
if len(dn) < 1 or len(dn) > 253:
return False
ldh_re = re.compile('^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$',
re.IGNORECASE)
return all(ldh_re.match(x) for x in dn.split('.'))
根据个人的目的,可以争论是否接受空域名。
答案 3 :(得分:3)
不要重新发明轮子。您可以使用一个库,例如验证者。或者,您可以复制their code:
pip install validators
import validators
if validators.domain('example.com')
print('this domain is valid')
答案 4 :(得分:1)
我喜欢Tim Pietzcker答案的彻底性,但为了便于阅读,我更倾向于从正则表达式中卸载一些逻辑。老实说,我必须查找那些(?
“扩展符号”部分的含义。另外,我觉得“双重否定”的方法更明显,因为它限制了正则表达式只是找到任何无效字符的责任。我确实喜欢re.IGNORECASE允许缩短正则表达式。
所以这是另一个镜头;它更长,但它有点像散文。我认为“可读”与“简洁”有些不一致。我相信到目前为止在线程中提到的所有验证约束都包括在内:
def isValidHostname(hostname):
if len(hostname) > 255:
return False
if hostname.endswith("."): # A single trailing dot is legal
hostname = hostname[:-1] # strip exactly one dot from the right, if present
disallowed = re.compile("[^A-Z\d-]", re.IGNORECASE)
return all( # Split by labels and verify individually
(label and len(label) <= 63 # length is within proper range
and not label.startswith("-") and not label.endswith("-") # no bordering hyphens
and not disallowed.search(label)) # contains only legal characters
for label in hostname.split("."))
答案 5 :(得分:0)
def is_valid_host(host):
'''IDN compatible domain validator'''
host = host.encode('idna').lower()
if not hasattr(is_valid_host, '_re'):
import re
is_valid_host._re = re.compile(r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$')
return bool(is_valid_host._re.match(host))
答案 6 :(得分:0)
免费提供@TimPietzcker答案。 Underscore 是有效的主机名字符(但不适用于域名)。虽然通常为IDN punycode域(例如xn--)找到双划线。应删除端口号。这是代码的清理。
import re
def is_valid_hostname(hostname):
if len(hostname) > 255:
return False
hostname = hostname.rstrip(".")
allowed = re.compile("(?!-)[A-Z\d\-\_]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
# convert your unicode hostname to punycode (python 3 )
# Remove the port number from hostname
normalise_host = hostname.encode("idna").decode().split(":")[0]
is_valid_hostanme(normalise_host )
答案 7 :(得分:0)
我认为此正则表达式可能对Python有帮助: '^([a-zA-Z0-9] +(\。| \-))* [a-zA-Z0-9] + $'
答案 8 :(得分:-1)
此纯正则表达式应满足所有参数:
^(?=.{1,253}\.?$)(?!-)[A-Za-z0-9\-]{1,63}(\.[A-Za-z0-9\-]{1,63})*\.?(?<!-)$
答案 9 :(得分:-2)
通过排除无效字符并确保非零长度来单独处理每个DNS标签。
def isValidHostname(hostname):
disallowed = re.compile("[^a-zA-Z\d\-]")
return all(map(lambda x: len(x) and not disallowed.search(x), hostname.split(".")))
答案 10 :(得分:-3)
如果您要验证现有主机的名称,最好的方法是尝试解决它。您永远不会编写正则表达式来提供该级别的验证。