ユーザーからurl
を受け取り、取得したHTMLで返信する必要があります。
URLの形式が正しくないかどうかを確認するにはどうすればよいですか?
例えば :
url='google' // Malformed
url='google.com' // Malformed
url='http://google.com' // Valid
url='http://google' // Malformed
どうすればこれを達成できますか?
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
実際、これが最良の方法だと思います。
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が実際に存在することを確認します。そうでない場合は、正しい形式であるかどうかを確認します。
編集:ああ、この質問はこれと重複しています: DjangoのバリデーターでURLが存在するかどうかを確認するにはどうすればよいですか?
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
)。
@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
今日、私はパダムの答えに基づいて、以下を使用します:
$ 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")
を使用してください。
それが役に立てば幸い!
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
文字列を「有効な」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])
編集
@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
を返します。
urllib
およびDjangoのような正規表現でURLを検証しますDjango URL検証正規表現は実際にはかなり良かったのですが、ユースケースに合わせて少し調整する必要がありました。 自由にあなたに合わせてください!
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
部分のみを検証します。 (これを適切に行うために、対応する正規表現用語と一致する2つの部分でurllib.parse.urlparse()
でURLを分割します。)netloc
部分は、スラッシュ/
が最初に現れる前に停止するため、port
番号はnetloc
の一部のままです。
https://www.google.com:80/search?q=python
^^^^^ ^^^^^^^^^^^^^^^^^
| |
| +-- netloc (aka "domain" in my code)
+-- scheme
IPv4アドレスも検証されます
URLバリデーターをIPv6アドレスでも機能させる場合は、次の手順を実行します。
is_valid_ipv6(ip)
を追加します。これは、本当に優れたIPv6バリデータ正規表現を持っています。and not is_valid_ipv6(domain)
を最後のif
に追加しますnetloc
(別名domain
)部分の実際の正規表現の例を次に示します。