2012-05-14 16 views
9

Sto cercando una funzione di libreria per normalizzare un URL in Python, ovvero rimuovere parti "./" o "../" nel percorso, o aggiungere una porta predefinita o caratteri speciali di escape e così via. Il risultato dovrebbe essere una stringa che è unica per due URL che puntano alla stessa pagina web. Ad esempio http://google.com e http://google.com:80/a/../ restituiscono lo stesso risultato.Canonicalizzare/normalizzare un URL?

Preferirei Python 3 e ho già controllato il modulo urllib. Offre funzioni per dividere gli URL ma nulla per canonicalizzarli. Java ha la funzione URI.normalize() che fa una cosa simile (anche se non considera la porta predefinita 80 uguale a nessuna porta data), ma c'è qualcosa come questo è python?

+0

Come nota a margine, una risorsa come 'http: // google.com /' non è la stessa di 'http: // google .it: 80/a /../ '. Cioè, se '/ a' non esiste, allora il secondo percorso fallirà. Per "canonicalizzare", perdi quel caso speciale e finisci con un URI valido quando hai iniziato con uno non valido ... –

risposta

0

Seguendo il numero good start, ho composto un metodo che si adatta alla maggior parte dei casi comunemente trovati nel web.

def urlnorm(base, link=''): 
    '''Normalizes an URL or a link relative to a base url. URLs that point to the same resource will return the same string.''' 
    new = urlparse(urljoin(base, url).lower()) 
    return urlunsplit((
    new.scheme, 
    (new.port == None) and (new.hostname + ":80") or new.netloc, 
    new.path, 
    new.query, 
    '')) 
4

ne dite di questo:

In [1]: from urllib.parse import urljoin 

In [2]: urljoin('http://example.com/a/b/c/../', '.') 
Out[2]: 'http://example.com/a/b/' 

Ispirato risposte alle this question. Non normalizza le porte, ma dovrebbe essere semplice creare una funzione che funzioni.

+0

Non ho "urllib.parse", ma ho "urlparse". – osa

+3

'urllib.parse' è il percorso di Python 3 - la domanda originale è stata posta su Py 3. –

4

Questo è quello che uso e che ha funzionato finora. Puoi ottenere urlnorm da pip.

Si noti che ordino i parametri della query. Ho trovato questo essenziale.

from urlparse import urlsplit, urlunsplit, parse_qsl 
from urllib import urlencode 
import urlnorm 

def canonizeurl(url): 
    split = urlsplit(urlnorm.norm(url)) 
    path = split[2].split(' ')[0] 

    while path.startswith('/..'): 
     path = path[3:] 

    while path.endswith('%20'): 
     path = path[:-3] 

    qs = urlencode(sorted(parse_qsl(split.query))) 
    return urlunsplit((split.scheme, split.netloc, path, qs, '')) 
+0

nice, rimuove le directory genitore non valide – hoju

+0

È necessario sostituire' split [2] .split ('') [0] 'con' urllib.parse.quote (split [2]) '- in alcuni casi, avere spazi in un URL è completamente normale, e di fatto richiesto. Inoltre, urlnorm è solo py2k –

+0

Inoltre, si sta scartando il frammento, che può effettivamente essere un componente URL richiesto, in alcuni casi insoliti. Sì, c'è un numero non nullo di pagine web in cui 'blah.com/# wat' è una pagina completamente diversa da' blah.com/'. In genere è fatto con javascript, ed è un enorme PITA, ma esiste. –

2

Il modulo urltools normalizza barre multiple, . e .. componenti senza rovinare la doppia barra in http://.

Una volta fatto pip install urltools l'utilizzo è la seguente:

print urltools.normalize('http://domain.com:80/a////b/../c') 
>>> 'http://domain.com/a/c' 
Problemi correlati