web-dev-qa-db-ja.com

Python-pythonでURLを検証する方法(不正な形式かどうか)

ユーザーからurlを受け取り、取得したHTMLで返信する必要があります。

URLの形式が正しくないかどうかを確認するにはどうすればよいですか?

例えば ​​:

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

どうすればこれを達成できますか?

87
Yugal Jindle

Django URL検証正規表現:

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

実際、これが最良の方法だと思います。

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_existsTrueに設定すると、URLが実際に存在することを確認します。そうでない場合は、正しい形式であるかどうかを確認します。

編集:ああ、この質問はこれと重複しています: DjangoのバリデーターでURLが存在するかどうかを確認するにはどうすればよいですか?

119
Drekembe

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

それをインストールします PyPIから with pip(pip install validators)。

95
Jabba

@DMfll回答に基づくTrueまたはFalseバージョン:

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

今日、私はパダムの答えに基づいて、以下を使用します:

$ 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")を使用してください。

それが役に立てば幸い!

11
jonaprieto

note-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
8
andrew cooke

文字列を「有効な」URLとして検証するための正しい方法を見つけようとして、私はこのページに行きました。ここでpython3を使用してソリューションを共有します。追加のライブラリは必要ありません。

Python2を使用している場合は、 https://docs.python.org/2/library/urlparse.html を参照してください。

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(scheme = ''、netloc = ''、path = 'dkakasdkjdjakdjadjfalskdjfalk'、params = ''、query = ''、fragment = '')

ParseResult(scheme = 'https'、netloc = 'stackoverflow.com'、path = ''、params = ''、query = ''、fragment = '')

'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])
7
DMfll

編集

@Kwameが指摘したように、以下のコードは、.comまたは.coなどが存在しない場合でもURLを検証します。

@Blaiseからも指摘されているように、 https://www.google のようなURLは有効なURLであり、解決するかどうかを個別に確認するためにDNSチェックを行う必要があります。

これは簡単で機能します。

したがって、min_attrには、URLの有効性を定義するために存在する必要がある文字列の基本セット、つまりhttp://部分とgoogle.com部分が含まれます。

urlparse.schemehttp://を保存し、

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を返します。

4
Padam Sethia

urllibおよびDjangoのような正規表現でURLを検証します

Django URL検証正規表現は実際にはかなり良かったのですが、ユースケースに合わせて少し調整する必要がありました。 自由にあなたに合わせてください!

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

説明

  • コードは、指定されたURLのschemeおよびnetloc部分のみを検証します。 (これを適切に行うために、対応する正規表現用語と一致する2つの部分でurllib.parse.urlparse()でURLを分割します。)
  • netloc部分は、スラッシュ/が最初に現れる前に停止するため、port番号はnetlocの一部のままです。

    https://www.google.com:80/search?q=python
    ^^^^^   ^^^^^^^^^^^^^^^^^
      |             |      
      |             +-- netloc (aka "domain" in my code)
      +-- scheme
    
  • IPv4アドレスも検証されます

IPv6サポート

URLバリデーターをIPv6アドレスでも機能させる場合は、次の手順を実行します。

  • Markus Jarderotの答え からis_valid_ipv6(ip)を追加します。これは、本当に優れたIPv6バリデータ正規表現を持っています。
  • and not is_valid_ipv6(domain)を最後のifに追加します

netloc(別名domain)部分の実際の正規表現の例を次に示します。

0
winklerrr