2010-01-25 3 views

Antwort

9

Hier ist, wie es Remember

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

zu tun, dass urljoin ein Pfad/Verzeichnis all bis zum letzten / betrachten - danach der Dateinamen, falls vorhanden.

Fügen Sie auch keine führende / zum zweiten Parameter hinzu, sonst erhalten Sie nicht das erwartete Ergebnis.

os.path Modul ist plattformabhängig, aber für Dateipfade, die nur Schrägstriche verwenden, aber keine URLs, die Sie verwenden könnten posixpath,normpath.

+0

Im Gegenteil: Wenn der zweite Parameter eine führende '/' hat, wird 'ftp: //domain.com /../ ..' zurückgegeben. Korrigieren. –

2

übernommen von os modul "- os.path ist eines der Module posixpath oder ntpath", in Ihrem Fall explizit mit posixpath.

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

'posixpath.normpath' tut nicht hilfreiche Dinge, wie das Entfernen von Schrägstrichen und das Erlauben eines doppelten Schrägstrichs. Ersetzt auch den leeren Pfad durch '.'. –

2

Weder urljoin noch posixpath.normpath den Job richtig. urljoin zwingt Sie, mit etwas beizutreten, und behandelt nicht absolut Pfade oder übermäßige .. s korrekt. posixpath.normpath reduziert mehrere Schrägstriche und entfernt nachfolgende Schrägstriche, die URLs nicht tun sollten.


Die folgende Funktion löst vollständig URLs, beid . s und s .. Handhabung in korrekter Weise RFC 3986 nach.

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) 

Sie können dann auf eine vollständige URL wie folgt aufrufen.

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

Weitere Informationen zu den Überlegungen, die gemacht werden müssen, wenn URLs Lösung finden a similar answer I wrote earlier on the subject.