Python 验证主机名字符串
后续行动Python 验证主机名字符串,python,regex,validation,hostname,fqdn,Python,Regex,Validation,Hostname,Fqdn,后续行动 作为参考,在Python中匹配/验证主机名/fqdn(完全限定域名)的最可读、最简洁的方法是什么?我已经回答了下面的问题,欢迎改进。通过排除无效字符并确保长度不为零,分别处理每个DNS标签 def isValidHostname(hostname): disallowed = re.compile("[^a-zA-Z\d\-]") return all(map(lambda x: len(x) and not disallowed.search(x), hostnam
作为参考,在Python中匹配/验证主机名/fqdn(完全限定域名)的最可读、最简洁的方法是什么?我已经回答了下面的问题,欢迎改进。通过排除无效字符并确保长度不为零,分别处理每个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(".")))
重新导入
def是有效的主机名(主机名):
如果len(主机名)>255:
返回错误
如果主机名[-1]==”:
hostname=hostname[:-1]#如果有,从右边正好去掉一个点
allowed=re.compile((?!-)[A-Z\d-]{1,63}(?如果您希望验证现有主机的名称,最好的方法是尝试解析它。您永远不会编写一个正则表达式来提供那种级别的验证。我喜欢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("."))
def isValidHostname(主机名):
如果len(主机名)>255:
返回错误
如果hostname.endswith(“.”):#单个尾随点是合法的
hostname=hostname[:-1]#如果有,从右边正好去掉一个点
disallowed=re.compile(“[^A-Z\d-]”,re.IGNORECASE)
返回所有(#按标签分割并单独验证
(label和len(label)这里有一个更严格的版本,有以下改进:
- 将主机名的长度限制为253个字符(去掉可选的尾随点后)
- 将字符集限制为ASCII(即使用
[0-9]
而不是\d
)
- 检查TLD是否全部为数字
重新导入
def是有效的主机名(主机名):
如果主机名[-1]==”:
#如果存在,则从右侧正好去掉一个点
主机名=主机名[:-1]
如果len(主机名)>253:
返回错误
labels=hostname.split(“.”)
#TLD不能全部为数字
如果重新匹配(r“[0-9]+$”,则标签[-1]):
返回错误
allowed=re.compile(r)(?!-)[a-z0-9-]{1,63}(?Per,DNS名称的最大长度为253个字符。(一个最多允许255个八位字节,但其中2个八位字节被编码占用。)
重新导入
def验证_fqdn(dn):
如果dn.endswith('.'):
dn=dn[:-1]
如果len(dn)<1或len(dn)>253:
返回错误
ldh_re=re.compile(“^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?”,
关于(不知情情况)
返回dn.split('.')中x的所有(ldh匹配(x))
人们可能会争论是否接受空域名,这取决于一个人的目的。对@TimPietzcker答案的补充。
是有效的主机名字符(但不适用于域名)。而双破折号通常用于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_hostname(normalise_host )
重新导入
def是有效的主机名(主机名):
如果len(主机名)>255:
返回错误
hostname=hostname.rstrip(“.”)
allowed=re.compile((?!-)[A-Z\d\-\\\\\\\\\\\\\{1,63}(?我认为这个正则表达式在Python中可能有帮助:
“^([a-zA-Z0-9]+(\.\124; \-)*[a-zA-Z0-9]+$”不要重新发明轮子。您可以使用库,例如验证程序。或者您可以复制:
装置
用法
返回全部(x且不被禁止。在主机名中搜索(x)x。拆分(“.”)
主机名末尾的尾随
是有效的。哦,如果您想支持IDN,当然还有很多工作要做……主机名标签也不应该以连字符结尾。您使用的re.match
不正确-请注意re.match(“A+”,“ab”)
是一个匹配,而re.match(“a+$,“ab”)
不是。您的函数也不允许在主机名的末尾有一个点。我一直认为re.match
需要匹配整个字符串,因此不需要字符串的结尾锚定。但我现在发现(谢谢!)它只将匹配项绑定到字符串的开头。我相应地更正了我的正则表达式。但是,我不明白你的第二点。将主机名结尾为点合法吗?问题中链接的维基百科文章似乎说不合法。@Tim Pietzcker是的,结尾只有一个点是合法的。它将该名称标记为完全限定的域名,这使得DNS系统知道它不应该尝试将本地域附加到其中。请注意,每个段也有63个字符的限制。整个主机名有一个255个字符的全局限制。如果他想知道一个还不存在的主机名是否是合法的,该怎么办?RFC看起来很简单,所以我不明白为什么要使用正则表达式不起作用。取决于您试图显示的内容。如果名称没有解析,那么谁知道它的“含义”;真正的验证方法需要正则表达式无法拥有的信息(即访问DNS)。尝试并处理失败会更容易。当考虑到可能合法但尚未合法的名称时,真正需要关心的人只有注册者。其他人都应该将这些事情留给在该领域拥有真正专业知识的代码。正如JWZ所指出的,应用RE会带来问题分为两个问题。(嗯,大部分…)我不同意。有两个独立的问题,两个都是有效的问题:(1)°论证给定字符串在技术上是否可以作为,比如,有效的电子邮件地址、主机名等;(2)°证明
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))
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)
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('.'))
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_hostname(normalise_host )
pip install validators
import validators
if validators.domain('example.com')
print('this domain is valid')