2010-01-25 4 views

Répondre

9

Voici comment faire

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

Rappelez-vous que urljoin considèrent comme un chemin/répertoire tous jusqu'au dernier / - après le nom du fichier, le cas échéant.

De même, n'ajoutez pas de / au second paramètre, sinon vous n'obtiendrez pas le résultat attendu.

os.path Le module est dépendant de la plate-forme, mais pour les chemins de fichier utilisant uniquement des barres obliques mais pas des URL, vous pouvez utiliser posixpath,normpath.

+0

Au contraire: Si le second paramètre a un préfixe '/', il retournera 'ftp: //domain.com /../ ..'. Corriger –

2

adopté à partir du module os "- os.path est l'un des modules posixpath, ou ntpath", dans votre cas, en utilisant explicitement posixpath.

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

'posixpath.normpath' fait des choses inutiles comme la suppression des barres obliques et la double barre oblique initiale. Remplace également le chemin vide par '.'. –

2

Ni urljoin ni posixpath.normpath faire le travail correctement. urljoin vous oblige à joindre quelque chose, et ne gère pas les chemins absolus ou .. s correctement. posixpath.normpath regroupe plusieurs barres obliques et supprime les barres obliques de fin, deux éléments que les URL ne doivent pas faire.


La fonction suivante résout complètement les URL, la manipulation et les deux . s .. s, d'une manière correcte en fonction de 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) 

Vous pouvez ensuite l'appeler sur une URL complète comme suit.

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

Pour plus d'informations sur les considérations qui doivent être prises lors de la résolution des URL, voir a similar answer I wrote earlier on the subject.

Questions connexes