29

ホスト名またはIPアドレスに一致する正規表現をフォローアップしますか?有効なホスト名の制限を参照として 使用して、Pythonでホスト名/ fqdn(完全修飾ドメイン名)を照合/検証するための最も読みやすく簡潔な方法は何ですか?私は以下の私の試みで答えました、改善は歓迎します。

4

10 に答える 10

54
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("."))

各セグメントが確実に

  • 少なくとも1文字と最大63文字が含まれます
  • 許可された文字のみで構成されます
  • ハイフンで開始または終了しません。

また、二重否定(not disallowed)を回避hostnameし、で終わる場合.も問題ありません。hostname複数のドットで終わる場合は失敗します(失敗するはずです) 。

于 2010-03-28T08:52:51.043 に答える
14

車輪の再発明をしないでください。バリデーターなどのライブラリを使用できます。または、コードをコピーすることもできます。

インストール

pip install validators

使用法

import validators
if validators.domain('example.com')
    print('this domain is valid')
于 2020-01-28T13:13:35.770 に答える
11

これは、 Tim Pietzckerの回答を少し厳密にしたもので、次の点が改善されています。

  • ホスト名の長さを253文字に制限します(オプションの末尾のドットを削除した後)。
  • 文字セットをASCIIに制限します(つまり、[0-9]の代わりに使用します\d)。
  • TLDがすべて数値ではないことを確認してください。
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)
于 2015-10-19T12:29:13.633 に答える
7

Old New Thingによると、DNS名の最大長は253文字です。(1つは最大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('.'))

目的に応じて、空のドメイン名を受け入れるかどうかを議論することができます。

于 2015-11-15T02:32:30.577 に答える
2

私はTimPietzckerの答えの徹底が好きですが、読みやすさのために正規表現からロジックの一部をオフロードすることを好みます。正直なところ、私はそれらの(?「拡張表記」部分の意味を調べなければなりませんでした。さらに、「ダブルネガティブ」アプローチは、正規表現の責任を無効な文字を見つけることだけに制限するという点で、より明白だと思います。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("."))
于 2010-03-28T21:06:51.490 に答える
1
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))
于 2011-06-13T11:42:42.497 に答える
1

@TimPietzckerの回答を無料で。 アンダースコアは有効なホスト名文字です(ただし、ドメイン名には使用できません)。二重ダッシュはIDNpunycodeドメイン(例: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 )
于 2017-04-04T15:08:58.597 に答える
-1

無効な文字を除外し、長さがゼロ以外であることを確認して、各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(".")))
于 2010-03-28T06:01:46.450 に答える
-1

この正規表現はPythonで役立つと思います:'^([a-zA-Z0-9] +(\。| \-))* [a-zA-Z0-9] + $'

于 2019-08-09T11:04:29.240 に答える
-3

既存のホストの名前を検証する場合は、それを解決するのが最善の方法です。そのレベルの検証を提供する正規表現を作成することは決してありません。

于 2010-03-28T11:51:38.093 に答える