Как проверить URL в Python? (Искажено или нет)

66

У меня есть url от пользователя, и я должен ответить с извлеченным HTML.

Как я могу проверить, что URL-адрес неверен?

Пример:

url='google'  // Malformed
url='google.com'  // Malformed
url='http://google.com'  // Valid
url='http://google'   // Malformed

Как мы можем достичь этого?

  • 1
  • 1
    Просто попробуйте прочитать его, если, например, httplib выдает исключение, то вы будете знать, что оно недопустимо. Не все правильно сформированные URL действительны !
Показать ещё 2 комментария
Теги:
url
malformedurlexception

8 ответов

55
Лучший ответ

Проверка URL-адреса django:

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
  • 0
    любопытство ... вы добавили ftp ? Или у меня старая версия Django?
  • 1
    url='www.google' искажен, но соответствует этому регулярному выражению.
Показать ещё 12 комментариев
103

Собственно, я думаю, что это лучший способ.

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-адрес, иначе он просто проверит, правильно ли он сформирован.

edit: ah yeah, этот вопрос является дубликатом этого: Как проверить, существует ли URL с помощью валидаторов Djangos?

  • 34
    Но это будет работать только в среде django, а не иначе.
  • 0
    Извините, я не знаю, почему я подумал, что в этом вопросе есть тег django. Извините, прости.
Показать ещё 4 комментария
85

Используйте 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).

  • 3
    Это выдаст ошибку для файла URL. Например, «file: ///users/file.txt»
  • 0
    Работает только для http и ftp URL.
Показать ещё 7 комментариев
29

Верная или ложная версия, основанная на ответе @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
True
False
True
  • 4
    Я не знал, что вы можете протестировать оператор if со списком ненулевых элементов. Это полезно Также +1 за использование встроенного модуля
  • 0
    Пустые списки отображаются в False в условиях условия.
Показать ещё 5 комментариев
8

note - lepl больше не поддерживается, извините (вы можете его использовать, и я думаю, что код ниже работает, но он не будет получать обновления).

rfc 3696 http://www.faqs.org/rfcs/rfc3696.html определяет, как это сделать (для http-адресов и электронной почты). Я выполнил свои рекомендации в python, используя lepl (библиотека парсеров). см. 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
  • 1
    Аккуратно, а как насчет FTP или HTTPS?
  • 6
    Вы не раздвоили код и не реализовали его? это с открытым исходным кодом.
Показать ещё 2 комментария
7

Я попал на эту страницу, пытаясь найти разумный способ проверить строки как "действительные" URL. Я поделюсь здесь своим решением, используя python3. Никаких дополнительных библиотек не требуется.

Смотрите https://docs.python.org/2/library/urlparse.html, если вы используете python2.

Смотрите https://docs.python.org/3.0/library/urllib.parse.html, если вы используете python3, как и я.

import urllib
from pprint import pprint

invalid_url = 'dkakasdkjdjakdjadjfalskdjfalk'
valid_url = 'http://qaru.site/'
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 (схема = '', netloc = '', путь = 'dkakasdkjdjakdjadjfalskdjfalk', params = '', query = '', фрагмент = '')

ParseResult (схема = 'https', netloc = 'stackoverflow.com', путь = '', params = '', query = '', фрагмент = '')

Строка 'dkakasdkjdjakdjadjfalskdjfalk' не имеет схемы или netloc.

1, вероятно, является действительным URL.

Вот более краткая функция:

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])
4

В настоящее время я использую следующее, основываясь на ответе 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").

Надеюсь, поможет!

  • 0
    Сбой в случае, если доменное имя начинается с тире, что недопустимо. tools.ietf.org/html/rfc952
2

РЕДАКТИРОВАТЬ

Как указывает @Kwame, приведенный ниже код действительно проверяет URL, даже если отсутствуют .com или .co т.д.

@Blaise также указал, что URL-адреса, такие как https://www.google, являются действительными, и вам необходимо выполнить проверку DNS, чтобы проверить, разрешает он или нет, отдельно.

Это просто и работает:

Таким образом, min_attr содержит базовый набор строк, которые должны присутствовать для определения действительности URL, то есть http:// part и google.com part.

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.

  • 0
    Пожалуйста, добавьте небольшое объяснение, что делает ваш код ...
  • 0
    Как насчет: url_check('https://www.google') возвращает True ?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню