2010-01-25 11 views

Respuesta

9

Aquí es cómo hacerlo

>>> import urlparse 
>>> urlparse.urljoin("ftp://domain.com/a/b/c/d/", "../..") 
'ftp://domain.com/a/b/' 
>>> urlparse.urljoin("ftp://domain.com/a/b/c/d/e.txt", "../..") 
'ftp://domain.com/a/b/'  

Recuerde que urljoin consideran un camino/directorio de todo hasta el último / - después de esto es el nombre del archivo, si la hay.

Además, no agregue un / al segundo parámetro, de lo contrario no obtendrá el resultado esperado.

os.path módulo depende de la plataforma, pero para rutas de archivos que utilizan solo barras, pero no URL, puede usar posixpath,normpath.

+0

Por el contrario: si el segundo parámetro tiene un '/', devolverá 'ftp: //domain.com /../ ..'. De corrección. –

2

adoptado del módulo os "- os.path es uno de los módulos posixpath, o ntpath", en su caso que usa explícitamente posixpath.

>>> import posixpath 
    >>> posixpath.normpath("https://stackoverflow.com/a/b/../c") 
    '/a/c' 
    >>> 
+2

'posixpath.normpath' hace cosas inútiles como eliminar barras diagonales y permitir doble barra inicial. También reemplaza la ruta vacía con '.'. –

2

Ni urljoin ni posixpath.normpath hacer el trabajo correctamente. urljoin lo obliga a unirse a algo, y no maneja rutas absolutas o excesivas .. s correctamente. posixpath.normpath colapsa varias barras diagonales y elimina las barras diagonales, ambas son cosas que las URL no deberían hacer.


La siguiente función resuelve URLs completamente, el manejo tanto de . s y .. s, de una forma correcta de acuerdo con RFC 3986.

try: 
    # Python 3 
    from urllib.parse import urlsplit, urlunsplit 
except ImportError: 
    # Python 2 
    from urlparse import urlsplit, urlunsplit 

def resolve_url(url): 
    parts = list(urlsplit(url)) 
    segments = parts[2].split('/') 
    segments = [segment + '/' for segment in segments[:-1]] + [segments[-1]] 
    resolved = [] 
    for segment in segments: 
     if segment in ('../', '..'): 
      if resolved[1:]: 
       resolved.pop() 
     elif segment not in ('./', '.'): 
      resolved.append(segment) 
    parts[2] = ''.join(resolved) 
    return urlunsplit(parts) 

A continuación, puede llamarlo en una URL completa de la siguiente manera.

>>> resolve_url("http://example.com/dir/../../thing/.") 
'http://example.com/thing/' 

Para obtener más información acerca de las consideraciones que se tienen que hacer en la resolución de direcciones URL, consulte a similar answer I wrote earlier on the subject.

Cuestiones relacionadas