2008-09-23 25 views
64

Me gustaría saber si normalizo una URL en python.Cómo puedo normalizar una URL en python

Por ejemplo, si tengo una cadena URL como: "http://www.example.com/foo sustancia viscosa/bar.html"

necesito una biblioteca en Python que transformará el espacio extra (o cualquier otro carácter no normalizada) a una adecuada URL.

+0

Hay una respuesta más arriba-hasta la fecha en StackOverflow aquí: http://stackoverflow.com/questions/10584861/canonize-normali ze-an-url-in-python/15629657 – stuckintheshuck

+1

No creo que sea mejor ... –

Respuesta

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

Esto solo cita el componente de ruta.

De lo contrario, se podría hacer: urllib.quote(url, safe=":/")

+2

Que solo cita todos los caracteres. Eso no lo ayudará. –

+0

En este ejemplo, también citará el carácter ':' (no todos). Gracias por el comentario. – tzot

21

uso urllib.quote o urllib.quote_plus

Desde el urllib documentation:

cotización (cadena [, salvo])

reemplazar caracteres especiales en la cadena usando el escape "% xx". Las letras, dígitos, y los caracteres "_.-" son nunca citados. El parámetro seguro opcional especifica caracteres adicionales que no se deben citar - su valor predeterminado es '/'.

Ejemplo: quote('/~connolly/') produce '/%7econnolly/'.

quote_plus (cadena [, salvo])

, como la cita(), pero también reemplaza espacios por signos de suma, como se requiere para citar valores del formulario HTML. Los signos más en la cadena original se escapan a menos que estén incluidos en la caja fuerte. También no tiene el valor predeterminado seguro para '/'.

EDIT: Usando urllib.quote o urllib.quote_plus en toda la URL mangle, como @ ΤΖΩΤΖΙΟΥ señala:

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

@ ΤΖΩΤΖΙΟΥ proporciona una función que utiliza urlparse.urlparse and urlparse.urlunparse para analizar la URL y solo codifica la ruta. Esto puede ser más útil para usted, aunque si está construyendo la URL de un protocolo y host conocido pero con una ruta sospechosa, probablemente podría hacer lo mismo para evitar urlparse y simplemente citar la parte sospechosa de la URL, concatenando con partes seguras conocidas.

+2

Entonces, ¿qué devuelve urllib.quote dado el url de ejemplo de la pregunta? – tzot

+1

Basura. ¿Por qué se acepta una respuesta obviamente incorrecta como solución? –

+0

@ ΤΖΩΤΖΙΟΥ: punto excelente. Dirigido al @Armin Ronacher: posiblemente porque el que responde y el que acepta no conocían el problema, no todos los problemas son obvios para todos. –

66

Eche un vistazo a este módulo: werkzeug.utils.(Ahora en werkzeug.urls)

La función que está buscando se llama "url_fix" y funciona así:

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

Se implementa en Werkzeug de la siguiente manera:

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

Si bien esto es de una http rfc2616 probablemente la solución más precisa, creo que es excesiva, ¿o extraño algo? –

+1

Sí. Probablemente te perdiste la pregunta. Él tiene una URL de la entrada del usuario y quiere convertirla adecuadamente en una URL real. (Aka: haz lo que hace la barra de direcciones de Firefox) –

+3

'url_fix' ahora se encuentra en' werkzeug.urls' – sebpiq

55

Real fix in Python 2.7 for that problem

La solución correcta fue:

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

Para obtener más información, véase Issue918368: "urllib doesn't correct server returned urls"

+4

Excelente respuesta, conciso y útil. Dado que este cambio estaba dentro de urllib, el código que desea hacer lo mismo debe 'importar urllib' y llamar' urllib.quote() 'con los parámetros anteriores. –

+0

Esto barfs en la letra ä, pero le doy mi voto porque es simple, y no requiere otra importación. – mlissner

+0

trabajado como encanto! exactamente lo que estaba buscando –

12

Debido a esta página es un buen resultado para las búsquedas en Google sobre el tema, creo que vale la pena mencionar un trabajo que se ha hecho sobre la normalización de URL con Python que va más allá de los caracteres de espacio URLEncoding. Por ejemplo, tratar con puertos predeterminados, carácteres, ausencia de barras diagonales, etc.

Cuando se desarrolló el formato de sindicación de Atom, hubo un debate sobre cómo normalizar las URL en formato canónico; esto está documentado en el artículo PaceCanonicalIds en la wiki de Atom/Pie. Ese artículo proporciona algunos buenos casos de prueba.

Creo que uno de los resultados de esta discusión fue la biblioteca urlnorm.py de Mark Nottingham, que he utilizado con buenos resultados en un par de proyectos. Sin embargo, esa secuencia de comandos no funciona con la URL dada en esta pregunta. Entonces, una mejor opción podría ser Sam Ruby's version of urlnorm.py, que maneja esa URL, y todos los casos de prueba antes mencionados de la wiki de Atom.

1

me encuentro con un problema tan: necesidad de citar el espacio solamente.

fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]") ayuda, pero es muy complicado.

Así que utilicé una forma simple: url = url.replace(' ', '%20'), no es perfecto, pero es la manera más simple y funciona para esta situación.

Cuestiones relacionadas