74 votes

Comment puis-je normaliser une URL en python

J'aimerais savoir comment normaliser une URL en python.

Par exemple, si j'ai une chaîne d'URL du type: "http://www.example.com/foo goo / bar.html"

J'ai besoin d'une bibliothèque en python qui transformera l'espace supplémentaire (ou tout autre caractère non normalisé) en une URL appropriée.

73voto

Armin Ronacher Points 16894

Regardez ce module: werkzeug.utils . (maintenant en werkzeug.urls )

La fonction que vous recherchez s'appelle "url_fix" et fonctionne comme ceci:

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

Il est implémenté à Werkzeug comme suit:

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

58voto

Oleg Sakharov Points 593

Véritable correctif dans Python 2.7 pour ce problème

La bonne solution était:

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

Pour plus d'informations, voir le problème 918368: "urllib ne corrige pas les URL renvoyées par le serveur".

24voto

Blair Conrad Points 56195

utiliser urllib.quote ou urllib.quote_plus

À partir de la urllib de la documentation:

citation(string[, coffre-fort])

Remplacer des caractères spéciaux dans la chaîne de à l'aide de la "%xx" s'échapper. Lettres, les chiffres et les caractères "_.-" sont jamais citée. La sécurité en option paramètre spécifie d'autres les caractères qui ne devrait pas être cité - sa valeur par défaut est '/'.

Exemple: quote('/~connolly/') rendements en '/%7econnolly/'.

quote_plus(string[, coffre-fort])

Comme quote(), mais également remplace les espaces par des signes plus, tel que requis pour la citation HTML les valeurs d'un formulaire. En Plus des signes dans le chaîne d'origine sont échappé à moins que ils sont inclus dans le coffre-fort. Il a également n'ont pas de sécurité par défaut est '/'.

EDIT: à l'Aide de urllib.devis ou urllib.quote_plus sur l'ensemble de l'URL sera mutilation, comme @ΤΖΩΤΖΙΟΥ points:

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

@ΤΖΩΤΖΙΟΥ fournit une fonction qui utilise urlparse.urlparse et urlparse.urlunparse pour analyser les url et seulement coder le chemin. Ce sera peut-être utile pour vous, même si vous êtes la construction de l'URL à partir d'un protocole connu et de l'hôte, mais avec un suspect chemin, vous pourriez probablement faire tout aussi bien pour éviter urlparse et de citer le suspect partie de l'URL, la concaténation avec la connaissance de la sécurité des pièces.

13voto

cobra libre Points 495

Parce que cette page est un résultat haut de la page pour les recherches Google sur le sujet, je pense qu'il est utile de mentionner certains travail qui a été fait sur l'URL de la normalisation avec Python qui va au-delà de l'encodage des caractères d'espacement. Par exemple, les rapports avec les ports par défaut, le caractère de cas, l'absence de barres obliques, etc.

Lorsque le format de syndication Atom est en cours d'élaboration, il y a des discussions sur la normalisation des URLs dans un format canonique; cela est décrit dans l'article PaceCanonicalIds sur l'Atome/Tarte wiki. Cet article fournit quelques bonnes cas de test.

Je crois que un des résultats de cette discussion était Mark Nottingham urlnorm.py bibliothèque, j'ai utilisé avec de bons résultats sur quelques projets. Ce script ne fonctionne pas avec l'URL donnée dans cette question, cependant. Donc un meilleur choix pourrait être Sam Ruby version de urlnorm.pyqui gère ce même URL, et tous ces cas de test à partir de l'Atome wiki.

10voto

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

Ceci ne cite que le composant path.

Sinon, vous pourriez faire: urllib.quote(url, safe=":/")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X