我url
来自用户,我必须用获取的HTML进行回复。
如何检查URL格式是否正确?
例如 :
url='google' // Malformed
url='google.com' // Malformed
url='http://google.com' // Valid
url='http://google' // Malformed
我们怎样才能做到这一点?
url='http://google'
没有格式错误。架构+主机名始终有效。
我url
来自用户,我必须用获取的HTML进行回复。
如何检查URL格式是否正确?
例如 :
url='google' // Malformed
url='google.com' // Malformed
url='http://google.com' // Valid
url='http://google' // Malformed
我们怎样才能做到这一点?
url='http://google'
没有格式错误。架构+主机名始终有效。
Answers:
import re
regex = re.compile(
r'^(?:http|ftp)s?://' # http:// or https://
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' #domain...
r'localhost|' #localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
print(re.match(regex, "http://www.example.com") is not None) # True
print(re.match(regex, "example.com") is not None) # False
ftp
吗?还是我有旧的Django版本?
http://[2001:0DB8::3]:8080/index.php?valid=true#result
实际上,我认为这是最好的方法。
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
val = URLValidator(verify_exists=False)
try:
val('http://www.google.com')
except ValidationError, e:
print e
如果设置verify_exists
为True
,它将实际验证该URL是否存在,否则将仅检查其格式是否正确。
编辑:是的,这个问题是重复的:我如何检查Django的验证程序是否存在URL?
verify_exists
不推荐使用。-1
verify_exists
不再存在。此外,val
也可以像变量一样调用它URLValidator()('http://www.google.com')
使用验证程序包:
>>> import validators
>>> validators.url("http://google.com")
True
>>> validators.url("http://google")
ValidationFailure(func=url, args={'value': 'http://google', 'require_tld': True})
>>> if not validators.url("http://google"):
... print "not valid"
...
not valid
>>>
使用pip()从PyPI安装它pip install validators
。
validators.url("http://localhost:8080") ValidationFailure(func=url, args={'public': False, 'value': 'http://localhost:8080'})
基于@DMfll的真假版本:
try:
# python2
from urlparse import urlparse
except:
# python3
from urllib.parse import urlparse
a = 'http://www.cwi.nl:80/%7Eguido/Python.html'
b = '/data/Python.html'
c = 532
d = u'dkakasdkjdjakdjadjfalskdjfalk'
def uri_validator(x):
try:
result = urlparse(x)
return all([result.scheme, result.netloc, result.path])
except:
return False
print(uri_validator(a))
print(uri_validator(b))
print(uri_validator(c))
print(uri_validator(d))
给出:
True
False
False
False
True
该字符串fake
,甚至返回一个空白字符串。永远不会有任何错误,因为这些属性始终存在,并且列表将始终具有布尔值True,因为它包含这些属性。即使所有属性均为“无”,列表仍将为非空。您需要对属性进行一些验证,因为所有事情都会像现在那样进行。
print("I am true") if [False, None, 0, '', [], {}] else print("I am false.")
打印“我是真的”。当我运行它时。[result.scheme, result.netloc, result.path]
总是计算为True
。print("I am True") if [] else print("I am False.")
打印“我是假的”。所以空列表是False。数组的内容需要使用类似all
函数的评估。
result.path
从测试中删除。
scheme
: if not all([result.scheme in ["file", "http", "https"], result.netloc, result.path]):
如今,我根据Padam的回答使用以下内容:
$ python --version
Python 3.6.5
这是它的外观:
from urllib.parse import urlparse
def is_url(url):
try:
result = urlparse(url)
return all([result.scheme, result.netloc])
except ValueError:
return False
只需使用is_url("http://www.asdf.com")
。
希望能帮助到你!
https://https://https://www.foo.bar
。
注意 -lepl不再受支持,对不起(欢迎您使用它,我认为以下代码可以运行,但不会获得更新)。
rfc 3696 http://www.faqs.org/rfcs/rfc3696.html定义了如何执行此操作(针对http网址和电子邮件)。我使用lepl(解析器库)在python中实现了其建议。看到http://acooke.org/lepl/rfc3696.html
使用:
> easy_install lepl
...
> python
...
>>> from lepl.apps.rfc3696 import HttpUrl
>>> validator = HttpUrl()
>>> validator('google')
False
>>> validator('http://google')
False
>>> validator('http://google.com')
True
我登陆此页面,试图找出一种合理的方法来将字符串验证为“有效” URL。我在这里分享我使用python3的解决方案。无需额外的库。
如果您使用的是python2,请参见https://docs.python.org/2/library/urlparse.html。
如果您按原样使用python3,请参阅https://docs.python.org/3.0/library/urllib.parse.html。
import urllib
from pprint import pprint
invalid_url = 'dkakasdkjdjakdjadjfalskdjfalk'
valid_url = 'https://stackoverflow.com'
tokens = [urllib.parse.urlparse(url) for url in (invalid_url, valid_url)]
for token in tokens:
pprint(token)
min_attributes = ('scheme', 'netloc') # add attrs to your liking
for token in tokens:
if not all([getattr(token, attr) for attr in min_attributes]):
error = "'{url}' string has no scheme or netloc.".format(url=token.geturl())
print(error)
else:
print("'{url}' is probably a valid url.".format(url=token.geturl()))
ParseResult(scheme ='',netloc ='',path ='dkakasdkjdjakdjadjfalskdjfalk',params ='',query ='',fragment =“'')
ParseResult(scheme ='https',netloc ='stackoverflow.com',path ='',params ='',query ='',fragment =“'')
'dkakasdkjdjakdjadjfalskdjfalk'字符串没有方案或netloc。
“ https://stackoverflow.com ”可能是有效的网址。
这是一个更简洁的功能:
from urllib.parse import urlparse
min_attributes = ('scheme', 'netloc')
def is_valid(url, qualifying=min_attributes):
tokens = urlparse(url)
return all([getattr(tokens, qualifying_attr)
for qualifying_attr in qualifying])
编辑
正如@Kwame指出的那样,即使
.com
or.co
等不存在,下面的代码也会验证网址。@Blaise也指出,类似https://www.google的URL是有效的URL,您需要分别进行DNS检查以检查其是否解析。
这很简单并且有效:
因此min_attr
包含定义URL有效性(即http://
,google.com
一部分)所需出现的基本字符串集。
urlparse.scheme
商店http://
和
urlparse.netloc
存储域名 google.com
from urlparse import urlparse
def url_check(url):
min_attr = ('scheme' , 'netloc')
try:
result = urlparse(url)
if all([result.scheme, result.netloc]):
return True
else:
return False
except:
return False
all()
如果其中所有变量都返回true,则返回true。因此,如果result.scheme
和result.netloc
存在(即具有某个值),则该URL有效,因此返回True
。
https://www.google
是有效的网址。它可能无法真正解决,但是如果您担心,则需要进行DNS检查。
urllib
和类似Django的正则表达式验证URLDjango URL验证正则表达式实际上非常好,但是我需要针对我的用例进行一些调整。 随时适应您的需求!
import re
import urllib
# Check https://regex101.com/r/A326u1/5 for reference
DOMAIN_FORMAT = re.compile(
r"(?:^(\w{1,255}):(.{1,255})@|^)" # http basic authentication [optional]
r"(?:(?:(?=\S{0,253}(?:$|:))" # check full domain length to be less than or equal to 253 (starting after http basic auth, stopping before port)
r"((?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+" # check for at least one subdomain (maximum length per subdomain: 63 characters), dashes in between allowed
r"(?:[a-z0-9]{1,63})))" # check for top level domain, no dashes allowed
r"|localhost)" # accept also "localhost" only
r"(:\d{1,5})?", # port [optional]
re.IGNORECASE
)
SCHEME_FORMAT = re.compile(
r"^(http|hxxp|ftp|fxp)s?$", # scheme: http(s) or ftp(s)
re.IGNORECASE
)
def validate_url(url: str):
url = url.strip()
if not url:
raise Exception("No URL specified")
if len(url) > 2048:
raise Exception("URL exceeds its maximum length of 2048 characters (given length={})".format(len(url)))
result = urllib.parse.urlparse(url)
scheme = result.scheme
domain = result.netloc
if not scheme:
raise Exception("No URL scheme specified")
if not re.fullmatch(SCHEME_FORMAT, scheme):
raise Exception("URL scheme must either be http(s) or ftp(s) (given scheme={})".format(scheme))
if not domain:
raise Exception("No URL domain specified")
if not re.fullmatch(DOMAIN_FORMAT, domain):
raise Exception("URL domain malformed (domain={})".format(domain))
return url
scheme
和netloc
部分。(为了正确执行此操作,我将URL分为urllib.parse.urlparse()
两个相应的部分,然后与相应的正则表达式匹配。)该netloc
零件在第一次出现斜线之前停止/
,因此port
数字仍然是的一部分netloc
,例如:
https://www.google.com:80/search?q=python
^^^^^ ^^^^^^^^^^^^^^^^^
| |
| +-- netloc (aka "domain" in my code)
+-- scheme
IPv4地址也经过验证
如果您希望URL验证程序也可以使用IPv6地址,请执行以下操作:
is_valid_ipv6(ip)
从Markus Jarderot的答案中添加,该答案具有非常好的IPv6验证器正则表达式and not is_valid_ipv6(domain)
到最后if
以下是实际netloc
(aka domain
)部分的正则表达式示例:
以上所有解决方案都将“ http://www.google.com/path,www.yahoo.com/path ”之类的字符串识别为有效。此解决方案始终可以正常工作
import re
# URL-link validation
ip_middle_octet = u"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))"
ip_last_octet = u"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))"
URL_PATTERN = re.compile(
u"^"
# protocol identifier
u"(?:(?:https?|ftp|rtsp|rtp|mmp)://)"
# user:pass authentication
u"(?:\S+(?::\S*)?@)?"
u"(?:"
u"(?P<private_ip>"
# IP address exclusion
# private & local networks
u"(?:localhost)|"
u"(?:(?:10|127)" + ip_middle_octet + u"{2}" + ip_last_octet + u")|"
u"(?:(?:169\.254|192\.168)" + ip_middle_octet + ip_last_octet + u")|"
u"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_octet + ip_last_octet + u"))"
u"|"
# IP address dotted notation octets
# excludes loopback network 0.0.0.0
# excludes reserved space >= 224.0.0.0
# excludes network & broadcast addresses
# (first & last IP address of each class)
u"(?P<public_ip>"
u"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])"
u"" + ip_middle_octet + u"{2}"
u"" + ip_last_octet + u")"
u"|"
# host name
u"(?:(?:[a-z\u00a1-\uffff0-9_-]-?)*[a-z\u00a1-\uffff0-9_-]+)"
# domain name
u"(?:\.(?:[a-z\u00a1-\uffff0-9_-]-?)*[a-z\u00a1-\uffff0-9_-]+)*"
# TLD identifier
u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))"
u")"
# port number
u"(?::\d{2,5})?"
# resource path
u"(?:/\S*)?"
# query string
u"(?:\?\S*)?"
u"$",
re.UNICODE | re.IGNORECASE
)
def url_validate(url):
""" URL string validation
"""
return re.compile(URL_PATTERN).match(url)