2012-05-14 11 views
9

Szukam funkcji bibliotecznej w celu normalizacji adresu URL w języku Python, czyli usunięcia części "./" lub "../" w ścieżce lub dodania portu domyślnego lub uniknięcia znaków specjalnych i tak dalej. Wynik powinien być łańcuchem unikatowym dla dwóch adresów URL wskazujących tę samą stronę internetową. Na przykład http://google.com i http://google.com:80/a/../ zwrócą ten sam wynik.Czy można przekształcić/znormalizować adres URL?

Wolałbym Python 3 i już przejrzałem moduł urllib. Oferuje funkcje podziału adresów URL, ale nie ma możliwości ich kanonizacji. Java ma funkcję URI.normalize(), która robi podobną rzecz (chociaż nie uważa domyślnego portu 80 równego brakowi danego portu), ale czy jest coś takiego w python?

+0

Na marginesie, zasobów, takich jak 'http: // google.com /' nie jest taka sama, niż 'http: // google .com: 80/a /../ '. Oznacza to, że jeśli '/ a' nie istnieje, to druga ścieżka zakończy się niepowodzeniem. Przez "kanonalizację" go, tracisz ten specjalny przypadek i kończy się na poprawnym identyfikatorze URI, gdy zaczynałeś od niepoprawnego ... –

Odpowiedz

0

Po good start, skomponowałem metodę, która pasuje do większości przypadków powszechnie spotykanych w Internecie.

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

Jak o tym:

In [1]: from urllib.parse import urljoin 

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

Zainspirowany odpowiedzi na this question. Nie normalizuje portów, ale powinno być proste, aby uruchomić funkcję, która to robi.

+0

Nie mam 'urllib.parse', ale mam' urlparse'. – osa

+3

'urllib.parse' to lokalizacja Pythona 3 - oryginalne pytanie zostało zadane o Py 3. –

4

To jest to, czego używam i jak dotąd działało. Możesz pobrać urlnorm z pip.

Zauważ, że sortuję parametry zapytania. Stwierdziłem, że jest to niezbędne.

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

ładne, usuwa niepoprawne katalogi nadrzędne – hoju

+0

Musisz zastąpić' split [2] .split ('') [0] 'z' urllib.parse.quote (split [2]) '- w niektórych przypadkach spacje w adresie URL są całkowicie normalne, aw rzeczywistości wymagane. Ponadto, urlnorm jest tylko py2k tylko –

+0

Ponadto, odrzucasz fragment, który w rzeczywistości może być wymaganym komponentem URL, w niektórych nietypowych przypadkach. Tak, istnieje niezerowa liczba stron internetowych, gdzie 'blah.com/# wat' to zupełnie inna strona niż" blah.com/". Zwykle robi się to z javascript i jest ogromnym PITA, ale istnieje. –

2

Moduł urltools normalizuje wiele ukośnik . i .. składników nie psując podwójne ukośnymi http://.

Gdy to zrobisz pip install urltools użycie jest następujący:

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