Yug*_*dle 93 python url malformedurlexception
我url来自用户,我必须回复提取的HTML.
如何检查URL是否格式错误?
例如 :
url='google' // Malformed
url='google.com' // Malformed
url='http://google.com' // Valid
url='http://google' // Malformed
Run Code Online (Sandbox Code Playgroud)
我们怎样才能做到这一点?
Dre*_*mbe 123
实际上,我认为这是最好的方式.
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
Run Code Online (Sandbox Code Playgroud)
如果设置verify_exists为True,它将实际验证URL是否存在,否则它将检查它是否正确形成.
编辑:啊是的,这个问题与此重复:如何检查Django的验证器是否存在URL?
Jab*_*bba 105
使用验证器包:
>>> 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
>>>
Run Code Online (Sandbox Code Playgroud)
使用pip()从PyPI安装它pip install validators.
cet*_*ver 76
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
Run Code Online (Sandbox Code Playgroud)
ale*_*mol 41
一个真或假的版本,基于@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))
Run Code Online (Sandbox Code Playgroud)
得到:
True
True
False
True
Run Code Online (Sandbox Code Playgroud)
jon*_*eto 13
如今,我根据Padam的回答使用以下内容:
$ python --version
Python 3.6.5
Run Code Online (Sandbox Code Playgroud)
这就是它的样子:
from urllib.parse import urlparse
def is_url(url):
try:
result = urlparse(url)
return all([result.scheme, result.netloc])
except ValueError:
return False
Run Code Online (Sandbox Code Playgroud)
只是用is_url("http://www.asdf.com").
希望能帮助到你!
注意 - 不再支持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
Run Code Online (Sandbox Code Playgroud)
我登陆此页面试图找出一种将字符串验证为"有效"网址的合理方法.我在这里使用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()))
Run Code Online (Sandbox Code Playgroud)
ParseResult(scheme ='',netloc ='',path ='dkakasdkjdjakdjadjfalskdjfalk',params ='',query ='',fragment ='')
ParseResult(scheme ='https',netloc ='stackoverflow.com',path ='',params ='',query ='',fragment ='')
'dkakasdkjdjakdjadjfalskdjfalk'字符串没有方案或netloc.
' https://stackoverflow.com '可能是一个有效的网址.
这是一个更简洁的功能:
import urllib
min_attributes = ('scheme', 'netloc')
def is_valid(url, qualifying=None):
qualifying = min_attributes if qualifying is None else qualifying
token = urllib.parse.urlparse(url)
return all([getattr(token, qualifying_attr)
for qualifying_attr in qualifying])
Run Code Online (Sandbox Code Playgroud)
小智 5
编辑
正如@Kwame 所指出的,即使
.comor.co等不存在,以下代码也会验证 url 。@Blaise 还指出,像https://www.google 这样的 URL 是一个有效的 URL,您需要单独进行 DNS 检查以检查它是否解析。
这很简单并且有效:
Somin_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
Run Code Online (Sandbox Code Playgroud)
all()如果其中的所有变量都返回 true,则返回 true。因此,如果result.scheme和result.netloc存在即具有某些值,则该 URL 有效并因此返回True。
这是一个正则表达式解决方案,因为投票最高的正则表达式不适用于顶级域等奇怪的情况。下面是一些测试用例。
regex = 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)
)
Run Code Online (Sandbox Code Playgroud)
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:
if regex.match(c):
print(c, regex.match(c).span()[1] - regex.match(c).span()[0] == len(c))
else:
print(c, False)
Run Code Online (Sandbox Code Playgroud)
编辑:按照 nickh 的建议将连字符添加到域中。