2010-01-25 14 views

risposta

9

Ecco come farlo

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

Ricordate che urljoin considerano un percorso/directory tutto fino all'ultimo / - dopo questo è il nome del file, se presente.

Inoltre, non aggiungere uno / leader al secondo parametro, altrimenti non si otterrà il risultato previsto.

os.path modulo dipende dalla piattaforma ma per i percorsi dei file che utilizzano solo barre ma non URL è possibile utilizzare posixpath,normpath.

+0

Al contrario: se il secondo parametro ha un prefisso '/', restituirà 'ftp: //domain.com /../ ..'. Correzione. –

2

adottato dal modulo os "- os.path è uno dei moduli posixpath, o ntpath", nel tuo caso esplicitamente utilizzando posixpath.

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

'posixpath.normpath' fa cose inutili come rimuovere le barre finali e consentire la doppia barra iniziale. Sostituisce anche il percorso vuoto con '.'. –

2

urljoinposixpath.normpath fare il lavoro correttamente. urljoin ti costringe a unirti a qualcosa, e non gestisce correttamente i percorsi assoluti o eccessivi ... posixpath.normpath elimina più barre e rimuove le barre finali, entrambe cose che gli URL non dovrebbero fare.


La seguente funzione risolve completamente URL, trattare sia . s e .. s, in modo corretto secondo 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) 

È quindi possibile chiamare su un URL completo come segue.

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

Per ulteriori informazioni sulle considerazioni che devono essere fatte durante la risoluzione degli URL, vedere a similar answer I wrote earlier on the subject.

Problemi correlati