Python - Как проверить URL в Python?(Искажено или нет) - PullRequest
85 голосов
/ 23 августа 2011

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

Как проверить, не поврежден ли URL или нет?

Например:

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

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

Ответы [ 9 ]

116 голосов
/ 23 августа 2011

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

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: ах да, этот вопрос является дубликатом этого: Как я могу проверить, существует ли URL с валидаторами Django?

93 голосов
/ 24 августа 2015

Используйте пакет для проверки :

>>> 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
>>>

Установите его из PyPI с помощью пункта (pip install validators).

67 голосов
/ 23 августа 2011

регулярное выражение проверки 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
39 голосов
/ 24 июня 2016

Верная или ложная версия, основанная на ответе @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
9 голосов
/ 22 сентября 2018

В настоящее время я использую следующее, основываясь на ответе Падама:

$ 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").

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

8 голосов
/ 25 августа 2011

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

rfc 3696 http://www.faqs.org/rfcs/rfc3696.html определяет, как это сделать (для URL-адресов 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
7 голосов
/ 29 марта 2016

Я попал на эту страницу, пытаясь найти разумный способ проверки строк как «действительных» 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 = '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 (схема = '', netloc = '', путь = 'dkakasdkjdjakdjadjfalskdjfalk', params = '', query = '', фрагмент = '')

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

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

'https://stackoverflow.com', вероятно, является действительным 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 голосов
/ 12 июля 2017

EDIT

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

также указано @Blaise, URL, как https://www.google, является действительным 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.

0 голосов
/ 24 апреля 2019

Проверка URL с помощью urllib и регулярного выражения, подобного Django

Регулярное выражение проверки URL Django было довольно хорошим, но мне нужно было немного его настроить для моего случая использования. Не стесняйтесь адаптировать его к своему!

Python 3.7

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.(Чтобы сделать это правильно, я разделил URL с помощью urllib.parse.urlparse() на две соответствующие части, которые затем сопоставляются с соответствующими терминами регулярных выражений.)
  • Часть netloc останавливается перед первым появлениемкосая черта /, поэтому port числа по-прежнему являются частью netloc, например:

    https://www.google.com:80/search?q=python
    ^^^^^   ^^^^^^^^^^^^^^^^^
      |             |      
      |             +-- netloc (aka "domain" in my code)
      +-- scheme
    
  • Адреса IPv4 также проверяются

Поддержка IPv6

Если вы хотите, чтобы средство проверки URL также работало с адресами IPv6, сделайте следующее:

  • Добавьте is_valid_ipv6(ip) из Ответ Маркуса Жардеро , который имеет действительно хорошее регулярное выражение валидатора IPv6
  • Добавление and not is_valid_ipv6(domain) к последнему if

Примеры

Вот несколько примеров регулярного выражениядля netloc (он же domain) в действии:

...