2010-07-19 14 views
7

Gibt es irgendwelche Werkzeuge, um einen URL-Vergleich in Python zu machen?Kanonische URL in Python vergleichen?

Zum Beispiel, wenn ich http://google.com und google.com/ habe, würde ich gerne wissen, dass sie wahrscheinlich die gleiche Website sein werden.

Wenn ich eine Regel manuell erstellen würde, könnte ich sie in Großbuchstaben schreiben, dann den http:// Teil entfernen und alles nach dem letzten alphanumerischen Zeichen löschen. Aber ich kann Fehler sehen, wie ich sicher bin Das kannst du auch.

Gibt es eine Bibliothek, die das tut? Wie würdest du es machen?

+0

möglich Duplikat: http://stackoverflow.com/questions/682367/ –

+0

Es wird nicht ohne X Ruf Post zwei _links_ lassen, aber Sie können so viele sind URLs wie Sie möchten, wenn Sie sie in Backquotes einfügen, damit der Parser sie nicht in Links konvertiert. Ich habe deine Frage bearbeitet, um zu zeigen, was ich denke, dass du meintest, aber wenn ich es falsch verstanden habe, bitte korrigiere es noch einmal, um mich zu korrigieren. –

+0

Oh, und noch etwas: Was genau meinen Sie mit "unscharfen" Vergleich? Es ist leicht zu sagen, dass "http: // google.com" und "google.com /" dasselbe sind, weil sie die exakt gleiche kanonische Form haben, aber das ist kein unscharfer Vergleich. Ein echter Fuzzy-Vergleich würde URLs identifizieren, die ähnlich, aber nicht identisch sind, selbst nachdem Sie sie in ein Standardformular konvertiert haben. –

Antwort

-1

Es ist nicht ‚fuzzy‘, es ist nur die ‚Distanz‘ zwischen zwei Strings finden:

http://pypi.python.org/pypi/python-Levenshtein/

ich alle Teile entfernen würde, die URL semantisch sinnvoll sind Parsen (Protokoll, Schrägstriche, etc.) Normalisieren Sie auf Kleinbuchstaben, führen Sie dann eine Livenstein-Distanz aus, und entscheiden Sie dann von dort aus, wie viele Unterschiede eine akzeptable Schwelle sind.

Nur eine Idee.

3

Dieses aus der Spitze von meinem Kopf:

def canonical_url(u): 
    u = u.lower() 
    if u.startswith("http://"): 
     u = u[7:] 
    if u.startswith("www."): 
     u = u[4:] 
    if u.endswith("/"): 
     u = u[:-1] 
    return u 

def same_urls(u1, u2): 
    return canonical_url(u1) == canonical_url(u2) 

Natürlich gibt es viel Platz für mehr mit diesem Hantieren. Regexes könnten besser sein als Start und Schluss mit, aber Sie bekommen die Idee.

+0

Das ist ähnlich dem, was ich bauen würde, wenn ich es manuell machen würde. Ich hatte gehofft, dass es eine Lib gibt, die das schon tut. Es scheint, als sollte es ein gelöstes Problem sein. –

+0

@Colin: Dies ist eines dieser Dinge, wo es einfach ist, es selbst zu tun, und eher, um Sie zu bekommen, was Sie wirklich wollen. Die Sache ist, dass es keine streng definierte "kanonische Form" einer URL gibt, also denkt jeder, der etwas will, etwas anderes. –

+0

Ich stimme Nicholas zu: Das ist nicht gut genug definiert, um eine Standarddefinition zu erhalten. Sie werden am besten bedient, wenn Sie es selbst schreiben. –

1

Sie könnten die Namen mit DNS suchen und sehen, ob sie auf die gleiche IP zeigen. Eine geringfügige String-Verarbeitung kann erforderlich sein, um verwirrende Zeichen zu entfernen.

from socket import gethostbyname_ex 

urls = ['http://google.com','google.com/','www.google.com/','news.google.com'] 

data = [] 
for orginalName in urls: 
    print 'url:',orginalName 
    name = orginalName.strip() 
    name = name.replace('http://','') 
    name = name.replace('http:','') 
    if name.find('/') > 0: 
     name = name[:name.find('/')] 
    if name.find('\\') > 0: 
     name = name[:name.find('\\')] 
    print 'dns lookup:', name 
    if name: 
     try: 
      result = gethostbyname_ex(name) 
     except: 
      continue # Unable to resolve 
     for ip in result[2]: 
      print 'ip:', ip 
      data.append((ip, orginalName)) 

print data 

Ergebnis:

url: http://google.com 
dns lookup: google.com 
ip: 66.102.11.104 
url: google.com/ 
dns lookup: google.com 
ip: 66.102.11.104 
url: www.google.com/ 
dns lookup: www.google.com 
ip: 66.102.11.104 
url: news.google.com 
dns lookup: news.google.com 
ip: 66.102.11.104 
[('66.102.11.104', 'http://google.com'), ('66.102.11.104', 'google.com/'), ('66.102.11.104', 'www.google.com/'), ('66.102.11.104', 'news.google.com')]