अजगर - अजगर में एक यूआरएल को कैसे मान्य किया जाए? (विकृत या नहीं)


116

मेरे पास urlउपयोगकर्ता से है और मुझे प्राप्त HTML के साथ उत्तर देना है।

मैं URL के विकृत होने या न होने की जांच कैसे कर सकता हूं?

उदाहरण के लिए :

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

हम इसे कैसे प्राप्त कर सकते हैं?



1
बस इसे पढ़ने की कोशिश करें, यदि उदाहरण के लिए, कॉम्प्लेक्सिब एक अपवाद फेंकता है, तो आपको पता होगा कि यह अमान्य था। सभी अच्छी तरह से बनाए गए url मान्य नहीं हैं !
carlpett 12

1
यह आपकी मदद करेगा: stackoverflow.com/questions/827557/…
ध्रुवपाठक

10
url='http://google' विकृत नहीं है। स्कीमा + होस्टनाम हमेशा मान्य होता है।
विक्टर जोरास

जवाबों:


90

django url सत्यापन रेगेक्स ( स्रोत ):

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

एक जिज्ञासा ... क्या आपने इसे जोड़ा ftp? या मेरे पास एक पुराना django संस्करण है?
रग्गरो तुर्रा

2
@ युगल-जिंदल साइटेडोमैन एक मान्य यूआरएल नहीं है। संग्रहालय इसलिए है क्योंकि .Museum एक शीर्ष-स्तरीय डोमेन है (ICANN [1] उन्हें परिभाषित करता है), और एक साइटोमैन नहीं है। [1] icann.org
glarrain

1
यह कोई उपयोगकर्ता नाम के साथ काम नहीं करता है : password@example.com शैली URL
एडम बैक्सटर


2
यह IPv6 urls के लिए काम नहीं करेगा, जिसका रूप हैhttp://[2001:0DB8::3]:8080/index.php?valid=true#result
cimnine

124

दरअसल, मुझे लगता है कि यह सबसे अच्छा तरीका है।

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 मौजूद है, अन्यथा यह ठीक से गठित होने पर जांच करेगा।

संपादित करें: आह, यह सवाल इस का एक डुप्लिकेट है: मैं कैसे जांच सकता हूं कि क्या एक URL Django के सत्यापनकर्ताओं के साथ मौजूद है?


46
लेकिन यह केवल django के वातावरण में काम करेगा अन्यथा नहीं।
युगल जिंदल

19
verify_existsपदावनत किया गया है। -1
g33kz0r

2
जोड़ें: django.conf आयात सेटिंग्स सेटिंग से ।configure (DEBUG = गलत) और इसे हटाने के लिए verify_exists को निकालें django 1.5 के साथ काम करने के लिए
Dukeatcoding

1
@YugalJindle सही है, लेकिन इसे Django से अलग करना लगभग तुच्छ है: D। इसलिए, मैं इस विधि का उपयोग करता हूं
swdev

7
ध्यान दें, django> = 1.5 के साथ verify_existsअब नहीं है। इसके अलावा valवेरिएबल के बजाय आप इसे कॉल कर सकते हैं जैसेURLValidator()('http://www.google.com')
luckydonald

122

सत्यापनकर्ता पैकेज का उपयोग करें :

>>> 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 install validators) के साथ स्थापित करें ।


5
यह फ़ाइल यूआरएल के लिए त्रुटि फेंक देगा। जैसे "फाइल: ///users/file.txt"
देवव्रत

2
लोकलहोस्टल के लिए फेल validators.url("http://localhost:8080") ValidationFailure(func=url, args={'public': False, 'value': 'http://localhost:8080'})
टॉम

5
@Lal ज़ैदा, इससे पहले कि आप कुछ इस तरह का दावा है, कुछ प्रयास डाल दिया और कोड की जांच, regexp वास्तव में काफी अच्छा है: validators.readthedocs.io/en/latest/_modules/validators/...
Drachenfels

1
पैकेज के मान्य fn में कई मनमानी सीमाएँ हैं, इसलिए इसे सामान्य समाधान के रूप में सुझाना एक भयानक सलाह है।
ivan_pozdeev

2
@ivan_pozdeev: यदि यह भयानक है, तो एक बेहतर उपाय सुझाएं
Jabba

62

@ ट्रू उत्तर पर आधारित एक सही या गलत संस्करण:

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

8
मुझे नहीं पता था कि आप गैर-तत्वों की सूची के साथ एक बयान का परीक्षण कर सकते हैं। यह मददगार है। इसके अलावा +1 बिल्ट-इन मॉड्यूल का उपयोग करने के लिए
मार्क मैक्समिस्टर 17

9
यह सब कुछ की अनुमति देता है। यह Trueस्ट्रिंग के लिए fakeया एक रिक्त स्ट्रिंग के लिए भी लौटता है । कभी भी कोई त्रुटि नहीं होगी क्योंकि वे विशेषताएँ हमेशा हैं, और सूची में हमेशा ट्रू का बूलियन मान होगा क्योंकि इसमें वे विशेषताएँ शामिल हैं। भले ही सभी विशेषताएँ कोई भी हों, फिर भी सूची गैर-रिक्त होगी। आपको विशेषताओं के कुछ सत्यापन की आवश्यकता है क्योंकि सब कुछ उस तरह से गुजरता है जैसा आपके पास अभी है।
12

3
झूठी वस्तुओं की सूची सच का मूल्यांकन करती है: print("I am true") if [False, None, 0, '', [], {}] else print("I am false.")प्रिंट "मैं सच हूं।" जब मैं इसे चलाता हूं। [result.scheme, result.netloc, result.path]हमेशा मूल्यांकन करता है Trueprint("I am True") if [] else print("I am False.")प्रिंट "मैं गलत हूँ।" इसलिए खाली सूची गलत हैं। सरणी की सामग्री को allफ़ंक्शन की तरह कुछ के साथ मूल्यांकन की आवश्यकता है ।
डम्फेल

3
निश्चित नहीं है कि आपको इस तरह से मार्ग की आवश्यकता क्यों होगी आपको result.pathपरीक्षण से हटा देना चाहिए ।
जरीनाव

1
यह मेरे लिए काफी अच्छा है, धन्यवाद। मैंने इसके लिए एक साधारण सत्यापन जोड़ा scheme: if not all([result.scheme in ["file", "http", "https"], result.netloc, result.path]):
अलेक्जेंडर फोर्टिन

20

आजकल, मैं पदम के उत्तर के आधार पर निम्नलिखित का उपयोग करता हूं:

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

आशा करता हूँ की ये काम करेगा!


यदि डोमेन नाम डैश से शुरू होता है, जो मान्य नहीं है, तो यह विफल हो जाता है। tools.ietf.org/html/rfc952
ब्योर्न

1
यह विशेष मामले में घटकों को विभाजित करने के लिए केवल अच्छा है कि यूआरआई को विकृत होने के लिए जाना जाता है । जैसा कि मैंने पहले इसी तरह के अन्य उत्तर के लिए उत्तर दिया था, यह विकृत यूआरआई की पुष्टि करता है, जैसे https://https://https://www.foo.bar
निगलना

9

नोट - लेप्ल अब समर्थित नहीं है, क्षमा करें (आप इसका उपयोग करने के लिए स्वागत करते हैं, और मुझे लगता है कि नीचे दिया गया कोड काम करता है, लेकिन यह अपडेट प्राप्त करने वाला नहीं है)।

rfc 3696 http://www.faqs.org/rfcs/rfc3696.html यह परिभाषित करता है कि यह कैसे करना है (http urls और ईमेल के लिए)। मैंने लेप्ल (एक पार्सर लाइब्रेरी) का उपयोग करके अजगर में अपनी सिफारिशें लागू कीं। देख 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

2
नीट, लेकिन एफ़टीपी या एचटीटीपीएस के बारे में क्या?
एडम पार्किन

6
आपने कोड को फोर्क नहीं किया है और उन्हें लागू किया है? यह खुला स्रोत है।
andrew Cooke

1
lepl अब लेखक द्वारा बंद है acooke.org/lepl/discontinued.html संपादित करें: हे, बस महसूस किया कि आप कर रहे हैं लेखक
एम्मेट बटलर

1
नोट: lepl.apps.rfc3696 पायथन 3.7.4 में काम नहीं कर रहा है
शील

9

मैं इस पृष्ठ पर उतरा हूं कि स्ट्रिंग्स को "मान्य" urls के रूप में मान्य करने के लिए एक सामान्य तरीका निकालने की कोशिश कर रहा हूं। मैं यहाँ 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()))

ParseResult (स्कीम = '', netloc = '', path = 'dkakasdkjdjdjdjjjjjalsalsddjfalk', params = '', query = '', fragment = "')

ParseResult (योजना = 'https', netloc = 'stackoverflow.com', path = '', params = '', query = '', fragment = '')

'dkakasdkjjjjddjadjfalskdjfalk' स्ट्रिंग की कोई योजना या नेटलोक नहीं है।

' https://stackoverflow.com ' संभवतः एक वैध यूआरएल है।

यहाँ एक और अधिक संक्षिप्त कार्य है:

from urllib.parse import urlparse

min_attributes = ('scheme', 'netloc')


def is_valid(url, qualifying=min_attributes):
    tokens = urlparse(url)
    return all([getattr(tokens, qualifying_attr)
                for qualifying_attr in qualifying])

4

संपादित करें

जैसा कि @Kwame द्वारा बताया गया है, निम्न कोड url को मान्य नहीं करता है भले ही वह मौजूद हो .comया .coआदि।

@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()सही है अगर इसके अंदर सभी चर सच लौटाता है। इसलिए यदि मौजूद है result.schemeऔर result.netlocउसका कुछ मूल्य है तो URL मान्य है और इसलिए वह लौटाता है True


ओह, अच्छा कैच .. मुझे लगता है मुझे अपना कोड वापस लेना होगा। आप क्या पसंद करते हैं, क्या regex को छोड़कर कोई अन्य विकल्प हैं।
पदम सेठिया

https://www.googleएक मान्य URL है। यह वास्तव में हल नहीं हो सकता है, लेकिन अगर आप इस बात की परवाह करते हैं कि आपको DNS चेक करने की आवश्यकता है।
ब्लेस


2

URL urllibऔर Django जैसी regex के साथ मान्य करें

Django URL सत्यापन रेगेक्स वास्तव में बहुत अच्छा था, लेकिन मुझे अपने उपयोग के मामले के लिए इसे थोड़ा मोड़ने की आवश्यकता थी। इसे अपने अनुकूल करने के लिए स्वतंत्र महसूस करें!

पायथन 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भाग को मान्य करता है । (इसे ठीक से करने के लिए, मैं 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 पतों के साथ भी काम करे, तो निम्न कार्य करें:

  • Markus Jarderot के उत्तरis_valid_ipv6(ip) से जोड़ें , जिसमें एक बहुत अच्छा IPv6 सत्यापनकर्ता regex है
  • and not is_valid_ipv6(domain)अंतिम में जोड़ेंif

उदाहरण

कार्रवाई में netloc(उर्फ domain) भाग के लिए रेगेक्स के कुछ उदाहरण यहां दिए गए हैं :


1

उपरोक्त सभी समाधान " http://www.google.com/path,www.yahoo.com/path " जैसे स्ट्रिंग को मान्य मानते हैं। यह समाधान हमेशा की तरह काम करना चाहिए

import re

# URL-link validation
ip_middle_octet = u"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))"
ip_last_octet = u"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))"

URL_PATTERN = re.compile(
                        u"^"
                        # protocol identifier
                        u"(?:(?:https?|ftp|rtsp|rtp|mmp)://)"
                        # user:pass authentication
                        u"(?:\S+(?::\S*)?@)?"
                        u"(?:"
                        u"(?P<private_ip>"
                        # IP address exclusion
                        # private & local networks
                        u"(?:localhost)|"
                        u"(?:(?:10|127)" + ip_middle_octet + u"{2}" + ip_last_octet + u")|"
                        u"(?:(?:169\.254|192\.168)" + ip_middle_octet + ip_last_octet + u")|"
                        u"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_octet + ip_last_octet + u"))"
                        u"|"
                        # IP address dotted notation octets
                        # excludes loopback network 0.0.0.0
                        # excludes reserved space >= 224.0.0.0
                        # excludes network & broadcast addresses
                        # (first & last IP address of each class)
                        u"(?P<public_ip>"
                        u"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])"
                        u"" + ip_middle_octet + u"{2}"
                        u"" + ip_last_octet + u")"
                        u"|"
                        # host name
                        u"(?:(?:[a-z\u00a1-\uffff0-9_-]-?)*[a-z\u00a1-\uffff0-9_-]+)"
                        # domain name
                        u"(?:\.(?:[a-z\u00a1-\uffff0-9_-]-?)*[a-z\u00a1-\uffff0-9_-]+)*"
                        # TLD identifier
                        u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))"
                        u")"
                        # port number
                        u"(?::\d{2,5})?"
                        # resource path
                        u"(?:/\S*)?"
                        # query string
                        u"(?:\?\S*)?"
                        u"$",
                        re.UNICODE | re.IGNORECASE
                       )
def url_validate(url):   
    """ URL string validation
    """                                                                                                                                                      
    return re.compile(URL_PATTERN).match(url)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.