ipaddress - Cómo validar la dirección IP en Python?
python get ip address (11)
Considere la dirección IPv4 como "ip".
if re.match(r''^((/d{1,2}|1/d{2}|2[0-4]/d|25[0-5])/.){3}(/d{1,2}|1/d{2}|2[0-4]/d|25[0-5])$'', ip):
print "Valid IP"
else:
print "Invalid IP"
Esta pregunta ya tiene una respuesta aquí:
¿Cuál es la mejor manera de validar que una IP ingresada por el usuario es válida? Viene como una cadena.
Creo que esto lo haría ...
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
Desde Python 3.4 en adelante, la mejor manera de verificar si una dirección IPv6 o IPv4 es correcta es usar el módulo Biblioteca de Python ipaddress
- biblioteca de manipulación IPv4 / IPv6 sa https://docs.python.org/3/library/ipaddress.html para la documentación completa.
Ejemplo:
#!/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])
Para otras versiones: Github, phihag / Philipp Hagemeister, "dirección de Python 3.3 para versiones anteriores de Python", https://github.com/phihag/ipaddress
El backport de phihag está disponible, por ejemplo, en Anaconda Python 2.7 y está incluido en Installer. sa https://docs.continuum.io/anaconda/pkg-docs
Para instalar con pip:
pip install ipaddress
sa: ipaddress 1.0.17, "Biblioteca de manipulación de IPv4 / IPv6", "Puerto del módulo de ipaddress de 3.3+", https://pypi.python.org/pypi/ipaddress/1.0.17
El módulo IPy (un módulo diseñado para tratar con direcciones IP) emitirá una excepción ValueError para direcciones no válidas.
>>> 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''
Sin embargo, al igual que la respuesta de Dustin, aceptará cosas como "4" y "192.168" ya que, como se mencionó, estas son representaciones válidas de las direcciones IP.
Si está utilizando Python 3.3 o posterior, ahora incluye el módulo 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
Para Python 2, puede obtener la misma funcionalidad usando ipaddress si instala python-ipaddress:
pip install ipaddress
Este módulo es compatible con Python 2 y proporciona una API muy similar a la del módulo ipaddress incluido en la Biblioteca de Python Standard desde Python 3.3. Más detalles here . En Python 2 necesitará convertir explícitamente la cadena de la dirección IP a unicode: ipaddress.ip_address(u''127.0.0.1'')
.
Espero que sea lo suficientemente simple y pitónico:
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()))
No lo analice. Solo pregunta.
import socket
try:
socket.inet_aton(addr)
# legal
except socket.error:
# Not legal
Solo necesitaba analizar las direcciones IP v4. Mi solución basada en la estrategia de Chills sigue:
def getIP():
valid = False
while not valid :
octets = raw_input( "Remote Machine IP Address:" ).strip().split(".")
try: valid=len( filter( lambda(item):0<=int(item)<256, octets) ) == 4
except: valid = False
return ".".join( octets )
Tengo que darle mucho crédito a Markus Jarderot por su publicación, la mayoría de mi publicación está inspirada en la suya.
Descubrí que la respuesta de Markus aún falla algunos de los ejemplos de IPv6 en el script de Perl al que hace referencia su respuesta.
Aquí está mi expresión regular que pasa todos los ejemplos en ese script de 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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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|1/d/d|[1-9]/d|/d)
(?:/.(?:25[0-4]|2[0-4]/d|1/d/d|[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)|/d/d?))? # With an optional CIDR routing prefix (0-128)
/s* # Trailing whitespace
$"""
También armé un script de Python para probar todos esos ejemplos de IPv6; está aquí en Pastebin porque era demasiado grande para publicar aquí.
Puede ejecutar el script con resultados de prueba y argumentos de ejemplo en forma de "[resultado] = [ejemplo]", así como:
python script.py Fail=::1.2.3.4: pass=::127.0.0.1 false=::: True=::1
o simplemente puede ejecutar todas las pruebas al especificar que no hay argumentos, por ejemplo:
python script.py
De todos modos, espero que esto ayude a alguien más!
Vine con esta versión simple novato
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)
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)?|1/d{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)?|1/d{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]/d/d|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|1/d/d|[1-9]?/d)
(?: /.
(?:25[0-4]|2[0-4]/d|1/d/d|[1-9]?/d)
){3}
)
/s* # Trailing whitespace
$
""", re.VERBOSE | re.IGNORECASE | re.DOTALL)
return pattern.match(ip) is not None
La versión IPv6 usa " (?:(?<=::)|(?<!::):)
", que podría reemplazarse por " (?(?<!::):)
" en motores regex que soportan condicionales con miradas alrededor. (es decir, PCRE, .NET)
Editar:
- Cayó la variante nativa.
- Se amplió la expresión regular para cumplir con el RFC.
- Se agregó otra expresión regular para direcciones IPv6.
Edit2:
Encontré algunos enlaces sobre cómo analizar las direcciones IPv6 con regex:
- Una expresión regular para direcciones IPv6 - Foros de InterMapper
- La expresión regular de trabajo IPv6 - Patrick''s playground blog
- test-ipv6-regex.pl - Script Perl con toneladas de casos de prueba. Parece que mi expresión regular falla en algunas de esas pruebas.
Edit3:
Finalmente logré escribir un patrón que supera todas las pruebas y con el que también estoy contento.
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