如何在 Python 中验证 IP 地址?[重复]

2025-01-22 08:45:00
admin
原创
103
摘要:问题描述:验证用户输入的 IP 是否有效的最佳方法是什么?它以字符串形式出现。解决方案 1:别去分析,直接问就好。import socket try: socket.inet_aton(addr) # legal except socket.error: # Not legal 解决...

问题描述:

验证用户输入的 IP 是否有效的最佳方法是什么?它以字符串形式出现。


解决方案 1:

别去分析,直接问就好。

import socket

try:
    socket.inet_aton(addr)
    # legal
except socket.error:
    # Not legal

解决方案 2:

从 Python 3.4 开始,检查 IPv6 或 IPv4 地址是否正确的最佳方法是使用 Python 标准库模块ipaddress- IPv4/IPv6 操作库 sa https://docs.python.org/3/library/ipaddress.html获取完整文档。

例子 :

#!/usr/bin/env python

import ipaddress
import sys

try:
    ip = ipaddress.ip_address(sys.argv[1])
    print('%s is a correct IP%s address.' % (ip, ip.version))
except ValueError:
    print('address/netmask is invalid: %s' % sys.argv[1])
except:
    print('Usage : %s  ip' % sys.argv[0])

对于其他版本:Github,phihag / Philipp Hagemeister,“适用于旧 Python 版本的 Python 3.3 的 ipaddress”,https://github.com/phihag/ipaddress

phihag 的反向移植可在 Anaconda Python 2.7 等程序中使用,并包含在安装程序中。sa https://docs.continuum.io/anaconda/pkg-docs

使用 pip 安装:

pip install ipaddress

sa: ipaddress 1.0.17,“IPv4/IPv6 操作库”,“3.3+ ipaddress 模块的端口”,https://pypi.python.org/pypi/ipaddress/1.0.17

解决方案 3:

import socket

def is_valid_ipv4_address(address):
    try:
        socket.inet_pton(socket.AF_INET, address)
    except AttributeError:  # no inet_pton here, sorry
        try:
            socket.inet_aton(address)
        except socket.error:
            return False
        return address.count('.') == 3
    except socket.error:  # not a valid address
        return False

    return True

def is_valid_ipv6_address(address):
    try:
        socket.inet_pton(socket.AF_INET6, address)
    except socket.error:  # not a valid address
        return False
    return True

解决方案 4:

IPy 模块(专门用于处理 IP 地址的模块)将对无效地址抛出 ValueError 异常。

>>> from IPy import IP
>>> IP('127.0.0.1')
IP('127.0.0.1')
>>> IP('277.0.0.1')
Traceback (most recent call last):
 ...
ValueError: '277.0.0.1': single byte must be 0 <= byte < 256
>>> IP('foobar')
Traceback (most recent call last):
 ...
ValueError: invalid literal for long() with base 10: 'foobar'

但是,就像达斯汀的回答一样,它会接受“4”和“192.168”之类的内容,因为如上所述,这些是 IP 地址的有效表示。

如果您使用的是 Python 3.3 或更高版本,它现在包含ipaddress 模块:

>>> import ipaddress
>>> ipaddress.ip_address('127.0.0.1')
IPv4Address('127.0.0.1')
>>> ipaddress.ip_address('277.0.0.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/ipaddress.py", line 54, in ip_address
    address)
ValueError: '277.0.0.1' does not appear to be an IPv4 or IPv6 address
>>> ipaddress.ip_address('foobar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/ipaddress.py", line 54, in ip_address
    address)
ValueError: 'foobar' does not appear to be an IPv4 or IPv6 address

对于 Python 2,如果安装了 python-ipaddress,则可以使用 ipaddress 获得相同的功能:

pip install ipaddress

该模块与 Python 2 兼容,并提供与 Python 3.3 以来包含在 Python 标准库中的 ipaddress 模块非常相似的 API。更多详细信息请见此处。在 Python 2 中,您需要将 IP 地址字符串明确转换为 unicode ipaddress.ip_address(u'127.0.0.1'):。

解决方案 5:

def is_valid_ip(ip):
    """Validates IP addresses.
    """
    return is_valid_ipv4(ip) or is_valid_ipv6(ip)

IPv4:

def is_valid_ipv4(ip):
    """Validates IPv4 addresses.
    """
    pattern = re.compile(r"""
        ^
        (?:
          # Dotted variants:
          (?:
            # Decimal 1-255 (no leading 0's)
            [3-9]d?|2(?:5[0-5]|[0-4]?d)?|1d{0,2}
          |
            0x0*[0-9a-f]{1,2}  # Hexadecimal 0x0 - 0xFF (possible leading 0's)
          |
            0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's)
          )
          (?:                  # Repeat 0-3 times, separated by a dot
            .
            (?:
              [3-9]d?|2(?:5[0-5]|[0-4]?d)?|1d{0,2}
            |
              0x0*[0-9a-f]{1,2}
            |
              0+[1-3]?[0-7]{0,2}
            )
          ){0,3}
        |
          0x0*[0-9a-f]{1,8}    # Hexadecimal notation, 0x0 - 0xffffffff
        |
          0+[0-3]?[0-7]{0,10}  # Octal notation, 0 - 037777777777
        |
          # Decimal notation, 1-4294967295:
          429496729[0-5]|42949672[0-8]d|4294967[01]dd|429496[0-6]d{3}|
          42949[0-5]d{4}|4294[0-8]d{5}|429[0-3]d{6}|42[0-8]d{7}|
          4[01]d{8}|[1-3]d{0,9}|[4-9]d{0,8}
        )
        $
    """, re.VERBOSE | re.IGNORECASE)
    return pattern.match(ip) is not None

IPv6:

def is_valid_ipv6(ip):
    """Validates IPv6 addresses.
    """
    pattern = re.compile(r"""
        ^
        s*                         # Leading whitespace
        (?!.*::.*::)                # Only a single whildcard allowed
        (?:(?!:)|:(?=:))            # Colon iff it would be part of a wildcard
        (?:                         # Repeat 6 times:
            [0-9a-f]{0,4}           #   A group of at most four hexadecimal digits
            (?:(?<=::)|(?<!::):)    #   Colon unless preceeded by wildcard
        ){6}                        #
        (?:                         # Either
            [0-9a-f]{0,4}           #   Another group
            (?:(?<=::)|(?<!::):)    #   Colon unless preceeded by wildcard
            [0-9a-f]{0,4}           #   Last group
            (?: (?<=::)             #   Colon iff preceeded by exacly one colon
             |  (?<!:)              #
             |  (?<=:) (?<!::) :    #
             )                      # OR
         |                          #   A v4 address with NO leading zeros 
            (?:25[0-4]|2[0-4]d|1dd|[1-9]?d)
            (?: .
                (?:25[0-4]|2[0-4]d|1dd|[1-9]?d)
            ){3}
        )
        s*                         # Trailing whitespace
        $
    """, re.VERBOSE | re.IGNORECASE | re.DOTALL)
    return pattern.match(ip) is not None

IPv6 版本使用“ ”,在支持带环视条件的正则表达式引擎上(?:(?<=::)|(?<!::):)可以将其替换为“ ”。 (例如 PCRE、.NET)(?(?<!::):)

编辑:

  • 放弃了原生变体。

  • 扩展正则表达式以符合 RFC。

  • 为 IPv6 地址添加了另一个正则表达式。

编辑2:

我发现一些链接讨论如何使用正则表达式解析 IPv6 地址:

  • IPv6 地址的正则表达式- InterMapper 论坛

  • 有效的 IPv6 正则表达式- Patrick 的游乐场博客

  • test-ipv6-regex.pl - 包含大量测试用例的 Perl 脚本。看来我的正则表达式在其中一些测试中失败了。

编辑3:

最后终于成功编写出一个通过所有测试的模式,而且我对此也很满意。

解决方案 6:

我希望它足够简单并且符合 Python 风格:

def is_valid_ip(ip):
    m = re.match(r"^(d{1,3}).(d{1,3}).(d{1,3}).(d{1,3})$", ip)
    return bool(m) and all(map(lambda n: 0 <= int(n) <= 255, m.groups()))

解决方案 7:

我认为这样就可以了...

def validIP(address):
    parts = address.split(".")
    if len(parts) != 4:
        return False
    for item in parts:
        if not 0 <= int(item) <= 255:
            return False
    return True

解决方案 8:

将 IPv4 地址视为“ip”。

if re.match(r'^((d{1,2}|1d{2}|2[0-4]d|25[0-5]).){3}(d{1,2}|1d{2}|2[0-4]d|25[0-5])$', ip):  
    print("Valid IP")  
else:
    print("Invalid IP")

解决方案 9:

我必须对 Markus Jarderot 的帖子给予高度评价 - 我的帖子的大部分内容都受到他的启发。

我发现 Markus 的回答仍然不符合他所引用的 Perl 脚本中的一些 IPv6 示例。

下面是我的正则表达式,它通过了该 Perl 脚本中的所有示例:

r"""^
     s* # Leading whitespace
     # Zero-width lookaheads to reject too many quartets
     (?:
        # 6 quartets, ending IPv4 address; no wildcards
        (?:[0-9a-f]{1,4}(?::(?!:))){6}
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 0-5 quartets, wildcard, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
        (?:::(?!:))
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 0-4 quartets, wildcard, 0-1 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:)))?
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 0-3 quartets, wildcard, 0-2 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,2}
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 0-2 quartets, wildcard, 0-3 quartets, ending IPv4 address
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,3}
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 0-1 quartets, wildcard, 0-4 quartets, ending IPv4 address
        (?:[0-9a-f]{1,4}){0,1}
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,4}
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # wildcard, 0-5 quartets, ending IPv4 address
        (?:::(?!:))
        (?:[0-9a-f]{1,4}(?::(?!:))){0,5}
             (?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)
        (?:.(?:25[0-4]|2[0-4]d|1dd|[1-9]d|d)){3}
      |
        # 8 quartets; no wildcards
        (?:[0-9a-f]{1,4}(?::(?!:))){7}[0-9a-f]{1,4}
      |
        # 0-7 quartets, wildcard
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,6}[0-9a-f]{1,4})?
        (?:::(?!:))
      |
        # 0-6 quartets, wildcard, 0-1 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,5}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:[0-9a-f]{1,4})?
      |
        # 0-5 quartets, wildcard, 0-2 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
      |
        # 0-4 quartets, wildcard, 0-3 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
      |
        # 0-3 quartets, wildcard, 0-4 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,2}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,3}[0-9a-f]{1,4})?
      |
        # 0-2 quartets, wildcard, 0-5 quartets
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,1}[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,4}[0-9a-f]{1,4})?
      |
        # 0-1 quartets, wildcard, 0-6 quartets
        (?:[0-9a-f]{1,4})?
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,5}[0-9a-f]{1,4})?
      |
        # wildcard, 0-7 quartets
        (?:::(?!:))
        (?:(?:[0-9a-f]{1,4}(?::(?!:))){0,6}[0-9a-f]{1,4})?
     )
     (?:/(?:1(?:2[0-7]|[01]d)|dd?))? # With an optional CIDR routing prefix (0-128)
     s* # Trailing whitespace
    $"""

我还编写了一个 Python 脚本来测试所有这些 IPv6 示例;它位于 Pastebin 上,因为它太大而无法在这里发布。

您可以以“[result]=[example]”的形式使用测试结果和示例参数运行脚本,如下所示:

python script.py Fail=::1.2.3.4: pass=::127.0.0.1 false=::: True=::1

或者您也可以简单地通过不指定任何参数来运行所有测试,例如:

python script.py

无论如何,我希望这对别人有帮助!

解决方案 10:

我想到了这个简单的版本

def ip_checkv4(ip):
        parts=ip.split(".")
        if len(parts)<4 or len(parts)>4:
            return "invalid IP length should be 4 not greater or less than 4"
        else:
            while len(parts)== 4:
                a=int(parts[0])
                b=int(parts[1])
                c=int(parts[2])
                d=int(parts[3])
                if a<= 0 or a == 127 :
                    return "invalid IP address"
                elif d == 0:
                    return "host id  should not be 0 or less than zero " 
                elif a>=255:
                    return "should not be 255 or greater than 255 or less than 0 A"
                elif b>=255 or b<0: 
                    return "should not be 255 or greater than 255 or less than 0 B"
                elif c>=255 or c<0:
                    return "should not be 255 or greater than 255 or less than 0 C"
                elif d>=255 or c<0:
                    return "should not be 255 or greater than 255 or less than 0 D"
                else:
                    return "Valid IP address ", ip
        
    p=raw_input("Enter IP address")
    print ip_checkv4(p)

解决方案 11:

我只需要解析 IP v4 地址。我基于 Chills 策略的解决方案如下:

def getIP():   

    valid = False  

    但无效:  

        octets = raw_input("远程机器 IP 地址:").strip().split(".")  

        尝试:valid=len(filter(lambda(item):0<=int(item)<256,octets)) == 4  

        除外:valid = False  

    返回".".join(octets)  

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用