webentwicklung-frage-antwort-db.com.de

Wie kann ich eine URL in python normalisieren?

Ich würde gerne wissen, ob ich eine URL in Python normalisiere.

Zum Beispiel, wenn ich eine URL-Zeichenfolge habe wie: " http://www.example.com/foo goo/bar.html"

Ich benötige eine Bibliothek in python), die das zusätzliche Leerzeichen (oder jedes andere nicht normalisierte Zeichen) in eine richtige URL umwandelt.

70
Tom Feiner

Schauen Sie sich dieses Modul an: werkzeug.utils . (jetzt in werkzeug.urls)

Die gesuchte Funktion heißt "url_fix" und funktioniert folgendermaßen:

>>> from werkzeug.urls import url_fix
>>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

Es ist wie folgt in Werkzeug implementiert:

import urllib
import urlparse

def url_fix(s, charset='utf-8'):
    """Sometimes you get an URL by a user that just isn't a real
    URL because it contains unsafe characters like ' ' and so on.  This
    function can fix some of the problems in a similar way browsers
    handle data entered by the user:

    >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
    'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

    :param charset: The target charset for the URL if the url was
                    given as unicode string.
    """
    if isinstance(s, unicode):
        s = s.encode(charset, 'ignore')
    scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
    path = urllib.quote(path, '/%')
    qs = urllib.quote_plus(qs, ':&=')
    return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
68
Armin Ronacher

Echtes Update in Python 2.7 für dieses Problem

Die richtige Lösung war:

 # percent encode url, fixing lame server errors for e.g, like space
 # within url paths.
 fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]")

Weitere Informationen finden Sie unter Issue918368: "urllib korrigiert nicht die vom Server zurückgegebenen URLs"

58
Oleg Sakharov

benutze urllib.quote oder urllib.quote_plus

Aus der rllib-Dokumentation :

quote (string [ safe])

Ersetzen Sie Sonderzeichen in Zeichenfolgen mit dem Escapezeichen "% xx". Buchstaben, Ziffern und die Zeichen "_.-" werden niemals in Anführungszeichen gesetzt. Der optionale Parameter safe gibt zusätzliche Zeichen an, die nicht in Anführungszeichen gesetzt werden sollen. Der Standardwert ist '/'.

Beispiel: quote('/~connolly/') ergibt '/%7econnolly/'.

quote_plus (string [ safe])

Entspricht quote (), ersetzt jedoch auch Leerzeichen durch Pluszeichen, wie zum Zitieren von HTML-Formularwerten erforderlich. Pluszeichen in der ursprünglichen Zeichenfolge werden ausgeblendet, sofern sie nicht im Safe enthalten sind. Es gibt auch keinen sicheren Standardwert für '/'.

BEARBEITEN: Wenn Sie urllib.quote oder urllib.quote_plus für die gesamte URL verwenden, wird die URL entstellt.

>>> quoted_url = urllib.quote('http://www.example.com/foo goo/bar.html')
>>> quoted_url
'http%3A//www.example.com/foo%20goo/bar.html'
>>> urllib2.urlopen(quoted_url)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python25\lib\urllib2.py", line 124, in urlopen
    return _opener.open(url, data)
  File "c:\python25\lib\urllib2.py", line 373, in open
    protocol = req.get_type()
  File "c:\python25\lib\urllib2.py", line 244, in get_type
    raise ValueError, "unknown url type: %s" % self.__original
ValueError: unknown url type: http%3A//www.example.com/foo%20goo/bar.html

@ ΤΖΩΤΖ bietet eine Funktion, die rlparse.urlparse und urlparse.urlunparse verwendet, um die URL zu analysieren und nur den Pfad zu codieren. Dies kann für Sie nützlicher sein, auch wenn Sie die URL aus einem bekannten Protokoll und einem Host zusammenstellen, jedoch mit einem verdächtigen Pfad, können Sie wahrscheinlich genauso gut eine URL vermeiden und nur den verdächtigen Teil der URL in Anführungszeichen setzen bekannte sichere Teile.

24
Blair Conrad

Da diese Seite ein Top-Ergebnis für die Google-Suche zu diesem Thema ist, sollten Sie einige Arbeiten zur URL-Normalisierung mit Python) erwähnen, die über die Urlencodierung von Leerzeichen hinausgehen mit Standardports, Groß- und Kleinschreibung, fehlenden Schrägstrichen usw.

Als das Syndikationsformat Atom) entwickelt wurde, gab es einige Diskussionen darüber, wie URLs in ein kanonisches Format umgewandelt werden können. Dies ist im Artikel PaceCanonicalIds über Atom/Pie dokumentiert Dieser Artikel enthält einige gute Testfälle.

Ich glaube, dass ein Ergebnis dieser Diskussion Mark Nottinghams rlnorm.py Bibliothek war, die ich bei einigen Projekten mit guten Ergebnissen verwendet habe. Dieses Skript funktioniert jedoch nicht mit der in dieser Frage angegebenen URL. Eine bessere Wahl könnte also sein: Sam Rubys Version von urlnorm.py , die diese URL verarbeitet, und alle oben genannten Testfälle aus dem Atom= Wiki.

13
cobra libre

Py3

from urllib.parse import urlparse, urlunparse, quote
def myquote(url):
    parts = urlparse(url)
    return urlunparse(parts._replace(path=quote(parts.path)))

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/~user/with%20space/index.html?a=1&b=2'

Py2

import urlparse, urllib
def myquote(url):
    parts = urlparse.urlparse(url)
    return urlparse.urlunparse(parts[:2] + (urllib.quote(parts[2]),) + parts[3:])

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/%7Euser/with%20space/index.html?a=1&b=2'

Dies zitiert nur die Pfadkomponente.

9
tzot

Nur zu Ihrer Information, urlnorm ist zu github umgezogen: http://Gist.github.com/246089

4
Mark Nottingham

Gültig für Python 3.5:

import urllib.parse

urllib.parse.quote([your_url], "\./_-:")

beispiel:

import urllib.parse

print(urllib.parse.quote("http://www.example.com/foo goo/bar.html", "\./_-:"))

die Ausgabe ist http://www.example.com/foo%20goo/bar.html

Schriftart: https://docs.python.org/3.5/library/urllib.parse.html?highlight=quote#urllib.parse.quote

2
Hélder Lima

Ich stoße auf ein solches Problem: Ich muss nur den Raum zitieren.

fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]") helfen, aber es ist zu kompliziert.

Also habe ich einen einfachen Weg gewählt: url = url.replace(' ', '%20'), es ist nicht perfekt, aber es ist der einfachste Weg und es funktioniert für diese Situation.

1
WKPlus