J'aimerais savoir si je normalise une URL en python.
Par exemple, si j'ai une chaîne d'URL comme: " 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 correcte.
Jetez un œil à ce module: werkzeug.utils . (maintenant en werkzeug.urls
)
La fonction que vous recherchez s'appelle "url_fix" et fonctionne comme ceci:
>>> 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'
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))
vrai 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 Issue918368: "urllib ne corrige pas les URL renvoyées par le serveur"
utilisez urllib.quote
ou urllib.quote_plus
De la documentation urllib :
quote (chaîne [ sûr])
Remplacez les caractères spéciaux dans la chaîne à l'aide de l'échappement "% xx". Les lettres, les chiffres et les caractères "_.-" ne sont jamais cités. Le paramètre optionnel sûr spécifie des caractères supplémentaires qui ne doivent pas être cités - sa valeur par défaut est '/'.
Exemple:
quote('/~connolly/')
donne'/%7econnolly/'
.quote_plus (chaîne [ sûr])
Comme quote (), mais remplace également les espaces par des signes plus, comme requis pour citer des valeurs de formulaire HTML. Les signes plus dans la chaîne d'origine sont échappés sauf s'ils sont inclus dans le coffre-fort. Il n'a pas non plus de valeur par défaut sûre pour '/'.
EDIT: L'utilisation de urllib.quote ou urllib.quote_plus sur l'URL entière le gâchera, comme le souligne @ ΤΖΩΤΖΙΟΥ:
>>> 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 rlparse.urlparse et urlparse.urlunparse pour analyser l'url et encoder uniquement le chemin. Cela peut être plus utile pour vous, bien que si vous créez l'URL à partir d'un protocole et d'un hôte connus mais avec un chemin suspect, vous pourriez probablement faire tout aussi bien pour éviter l'analyse d'url et simplement citer la partie suspecte de l'URL, concaténée avec parties sûres connues.
Étant donné que cette page est le meilleur résultat pour les recherches Google sur le sujet, je pense qu'il vaut la peine de mentionner certains travaux qui ont été effectués sur la normalisation des URL avec Python qui va au-delà du codage url des caractères d'espace. Par exemple, le traitement avec ports par défaut, casse de caractères, manque de barres obliques, etc.
Lorsque le format de syndication Atom était en cours de développement, il y avait une discussion sur la façon de normaliser les URL au format canonique; cela est documenté dans l'article PaceCanonicalIds sur Atom/Pie Cet article fournit de bons cas de test.
Je crois que l'un des résultats de cette discussion a été la bibliothèque rlnorm.py de Mark Nottingham, que j'ai utilisée avec de bons résultats sur quelques projets. Cependant, ce script ne fonctionne pas avec l'URL indiquée dans cette question. Donc, un meilleur choix pourrait être la version de Sam Ruby de urlnorm.py , qui gère cette URL, et tous les cas de test susmentionnés du wiki Atom wiki.
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'
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'
Cela ne cite que le composant chemin.
Juste pour info, urlnorm est passé à github: http://Gist.github.com/246089
Valable pour Python 3.5:
import urllib.parse
urllib.parse.quote([your_url], "\./_-:")
exemple:
import urllib.parse
print(urllib.parse.quote("http://www.example.com/foo goo/bar.html", "\./_-:"))
la sortie sera http://www.example.com/foo%20goo/bar.html
Police: https://docs.python.org/3.5/library/urllib.parse.html?highlight=quote#urllib.parse.quote
Je rencontre un tel problème: besoin de citer uniquement l'espace.
fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]")
aide, mais c'est trop compliqué.
J'ai donc utilisé un moyen simple: url = url.replace(' ', '%20')
, ce n'est pas parfait, mais c'est le moyen le plus simple et cela fonctionne pour cette situation.