我从用户那里得到了url
并需要返回获取的HTML。
我如何检查URL是否格式不正确?
例如:
url = 'google' # Malformed
url = 'google.com' # Malformed
url = 'http://google.com' # Valid
url = 'http://google' # Malformed
我从用户那里得到了url
并需要返回获取的HTML。
我如何检查URL是否格式不正确?
例如:
url = 'google' # Malformed
url = 'google.com' # Malformed
url = 'http://google.com' # Valid
url = 'http://google' # Malformed
使用 validators 包:
>>> 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(pip install validators
)从PyPI安装validators。
ValidationFailure(func=url, args={'public': False, 'value': 'http://localhost:8080'})
- Tomhttp://www.google
,http://google.www
等网址。这只是检查 http://
和两个单词之间的 点(.)
是否存在。 - Lal实际上,我认为这是最好的方法。
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是否存在,否则它只会检查URL的格式是否正确。verify_exists
。此外,您可以使用以下方式调用URLValidator()
来替代val
变量:URLValidator()('http://www.google.com')
。 - luckydonald基于 @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'
e = 'https://stackoverflow.com'
def uri_validator(x):
try:
result = urlparse(x)
return all([result.scheme, result.netloc])
except:
return False
print(uri_validator(a))
print(uri_validator(b))
print(uri_validator(c))
print(uri_validator(d))
print(uri_validator(e))
给出:
True
False
False
False
True
print("I am true") if [False, None, 0, '', [], {}] else print("I am false.")
时,会打印出"I am true."。 [result.scheme, result.netloc, result.path]
的值始终为 True
。当运行 print("I am True") if [] else print("I am False.")
时,会打印出"I am false.",因此空列表为False。需要使用类似于all
函数的东西来评估数组的内容。 - dmmfllresult.path
。 - Jerinawscheme
添加了一个简单的验证:if not all([result.scheme in ["file", "http", "https"], result.netloc, result.path]):
- Alexander Fortinimport 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版本太旧了? - Ruggero Turrahttp://[2001:0DB8::3]:8080/index.php?valid=true#result
。 - cimnine现在,我使用以下内容,基于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
。 - ingyhere我来到这个页面是为了找出一种合理的方法来验证字符串是否为“有效”的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'可能是一个有效的URL。
这里有一个更简洁的函数:
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])
注意- 对不起,lepl不再受支持(您可以使用它,并且我认为下面的代码可以工作,但是它将不会得到更新)。
rfc 3696 http://www.faqs.org/rfcs/rfc3696.html定义了如何实现这一点(用于http url和电子邮件)。我使用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
编辑
正如@Kwame所指出的,即使没有
.com
或.co
等,下面的代码也可以验证url。@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
是一个有效的URL。它可能实际上无法解析,但如果您关心这一点,您需要进行DNS检查。 - Blaiseregex = re.compile(
r"(\w+://)?" # protocol (optional)
r"(\w+\.)?" # host (optional)
r"(([\w-]+)\.(\w+))" # domain
r"(\.\w+)*" # top-level domain (optional, can have > 1)
r"([\w\-\._\~/]*)*(?<!\.)" # path, params, anchors, etc. (optional)
)
cases = [
"http://www.google.com",
"https://www.google.com",
"http://google.com",
"https://google.com",
"www.google.com",
"google.com",
"http://www.google.com/~as_db3.2123/134-1a",
"https://www.google.com/~as_db3.2123/134-1a",
"http://google.com/~as_db3.2123/134-1a",
"https://google.com/~as_db3.2123/134-1a",
"www.google.com/~as_db3.2123/134-1a",
"google.com/~as_db3.2123/134-1a",
# .co.uk top level
"http://www.google.co.uk",
"https://www.google.co.uk",
"http://google.co.uk",
"https://google.co.uk",
"www.google.co.uk",
"google.co.uk",
"http://www.google.co.uk/~as_db3.2123/134-1a",
"https://www.google.co.uk/~as_db3.2123/134-1a",
"http://google.co.uk/~as_db3.2123/134-1a",
"https://google.co.uk/~as_db3.2123/134-1a",
"www.google.co.uk/~as_db3.2123/134-1a",
"google.co.uk/~as_db3.2123/134-1a",
"https://...",
"https://..",
"https://.",
"https://.google.com",
"https://..google.com",
"https://...google.com",
"https://.google..com",
"https://.google...com"
"https://...google..com",
"https://...google...com",
".google.com",
".google.co."
"https://google.co."
]
for c in cases:
print(c, regex.match(c).span()[1] - regex.match(c).span()[0] == len(c))
编辑:根据nickh的建议,将域名添加了连字符。
print(c, x.span()[1] - x.span()[0] == len(c) if (x := regex.match(c)) else False)
- pmiguelpintoAttributeError: 'NoneType' object has no attribute 'span'
。 - colin0117可以使用Pydantic来实现。我不太熟悉它的限制,但这是一个选项,没有人建议过。
我看到许多人在之前的答案中对ftp和文件URL提出了疑问,因此建议查阅文档,因为Pydantic有许多用于验证的类型,如FileUrl、AnyUrl甚至数据库URL类型。
以下是一个简单的使用示例:
from requests import get, HTTPError, ConnectionError
from pydantic import BaseModel, AnyHttpUrl, ValidationError
class MyConfModel(BaseModel):
URI: AnyHttpUrl
try:
myAddress = MyConfModel(URI = "http://myurl.com/")
req = get(myAddress.URI, verify=False)
print(myAddress.URI)
except(ValidationError):
print('Invalid destination')
Pydantic还会引发异常(pydantic.ValidationError),可用于处理错误。
我已使用以下模式进行了测试:
url='http://google'
并不是格式错误的。模式 + 主机名组合始终是有效的。 - Viktor Joras