2012-03-24 8 views
1

ich herauszufinden, die beste Art und Weise, wie wenn zwei oder mehr url im Fall dupliziert überprüfen sie einige zusätzliche Parameter, wie dem folgenden Code haben. In fac ist url1 und url2 gleich, aber wenn der Webspider ausgeführt wird, wird er als zwei separate URLs behandelt und das Ergebnis wird dupliziert.Der beste Weg, doppelte URL in Python zu überprüfen?

from urllib2 import urlopen 
import hashlib 

url1 = urlopen('http://www.time.com/time/nation/article/0,8599,2109975,00.html?xid=gonewssedit') 
u1 = hashlib.md5(u1).hexdigest() 
url2 = urlopen('http://www.time.com/time/nation/article/0,8599,2109975,00.html') 
u2 = hashlib.md5(u2).hexdigest() 
if u1 == u2: 
    print 'yes' 
else: 
    print 'no' 

Kurz gesagt, werde ich den MD5-Hash generiert, indem Sie den URL-Header verwendet wird, dann speichern Sie es in der Datenbank, dann, wenn ich die neue URL kriechen kann ich überprüfen, wenn es dupliziert wird oder nicht. Aber ich bin mir nicht sicher, ob es der beste Weg zu dieser Arbeit in Python ist.

Vielen Dank

Antwort

3

Das Ergebnis der Webseite kann gleich oder verschieden, je nach ‚zusätzlichen Parametern‘ sein. Daher können Sie Regeln, die doppelte Inhalte erkennen, im Allgemeinen nur durch Betrachten der URL nicht definieren.

würde ich vorschlagen, url1 und url2 als different.Compute eine MD5-Summe von jedem Block sagen 1024 Worte aus dem Urls empfangen zu behandeln. Pflegen Sie eine Hash-Map dieser md5sums, um Dubletten erkennen zu können.

Wahrscheinlich einige der Funktionen einige web crawling tools könnten Sie benötigen bieten.

Update basierend auf OP-Kommentare: Ich schrieb einen Code, um meine Antwort zu verbessern. Es gibt zwei Versionen: die erste ist einfacher:

def find_matches(): 
    """ 
     Basic version: reads urls, but does not consider the semantic information of 
     HTML header, body, etc. while computing duplicates. 
    """ 

    from urllib2 import urlopen 
    import hashlib 

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

    d = {} 
    url_contents = {} 
    matches = [] 
    for url in urls: 
     c = urlopen(url) 
     url_contents[url] = [] 
     while 1: 
      r = c.read(4096) 
      if not r: break 
      md5 = hashlib.md5(r).hexdigest() 
      url_contents[url].append(md5) 
      if md5 in d: 
       url2 = d[md5] 
       matches.append((md5, url, url2)) 
      else: 
       d[md5] = [] 
      d[md5].append(url) 
    #print url_contents 
    print matches 

if __name__ == '__main__': 
    find_matches() 

Es war naiv der obige Code zu erwarten Duplikate zu erkennen, in der erwarteten Art und Weise: die aktuellen Web-Seiten sind viel zu komplex. Daher haben sogar zwei URLs, die für die Augen eines Benutzers die gleichen sind, tatsächlich viele Unterschiede aufgrund von Anzeigen, Hash-Tags, Selbst-URL-Namenseinschluss usw.

Die zweite Version ist anspruchsvoller. Es führt eine begrenzte semantische Analyse des Inhalts basierend auf BeautifulSoup:

def find_matches(): 
    """ 
     Some consideration of the HTML header, body, etc. while computing duplicates. 
    """ 

    from urllib2 import urlopen 
    import hashlib 
    from BeautifulSoup import BeautifulSoup 
    import pprint 

    urls = [ 'http://www.google.com', 'http://www.google.com/search'] # assuming all distinct urls 

    def txt_md5(txt): 
     return hashlib.md5(txt).hexdigest() 

    MAX_FILE_SIZE = 1024*1024*1024 
    d = {} 
    url_contents = {} 
    matches = [] 
    for url in urls: 
     try: 
      c = urlopen(url) 
      url_contents[url] = [] 
      r = c.read(MAX_FILE_SIZE) 
      soup = BeautifulSoup(r) 
      header = soup.find('head').text 
      body = soup.find('body').text 
      # More fine-grained content options 
      # like h1, h2, p, etc., can be included. 
      # Common CSS tags like page, content, etc. 
      # can also be included. 
      for h in [header, body]: 
       print h 
       md5 = txt_md5(h) 
       url_contents[url].append((md5, h)) 
       if md5 in d: 
        url2 = d[md5] 
        matches.append((md5, url, url2)) 
       else: 
        d[md5] = [] 
       d[md5].append(url) 
     except Exception as e: 
      print "Exception", e 
    print '---------------' 
    #pprint.pprint(url_contents) 
    print matches 

if __name__ == '__main__': 
    find_matches() 

Aber auch die zweite Version funktioniert nicht. Der Grund bleibt gleich. Tatsächlich war der Unterschied zwischen den Kopftexten der beiden URLs ein eingeschlossener Hashwert und der Unterschied zwischen den Textstellen der beiden URLs war eine Zeichenkette webhp. Ich benutzte difflib.context_diff, um den Unterschied zu berechnen.

Es ist möglich, den Code zu verbessern, um eine dritte Version enthält, die die Web-Seiten mehr intelligent analysiert und berechnet die diff intelligent mehr. Zum Beispiel deklarieren Sie als Duplikate sogar die Texte mit < 5% diff (dieses Verhältnis kann leicht mit einer difflib-Funktion berechnet werden).

+0

hallo phaedurs, das ist wunderbar. ich danke Ihnen sehr für Ihre Antwort. Würden Sie mir gerne einige detaillierte Tipps geben, wie Sie "eine Hash-Karte dieser md5sums verwalten, um Dubletten erkennen zu können". Eigentlich habe ich rabiat gelernt, aber es ist ziemlich kompliziert zu meinem aktuellen Projekt. – mrblue

1

Es gibt keine Möglichkeit, ob zwei URIs auf die gleiche Ressource verweisen zu wissen, ohne beide abruft. Und selbst wenn sie grundsätzlich den gleichen Inhalt haben, können sie dynamische Elemente enthalten, z. B. Anzeigen, die sich bei jeder Anfrage ändern, wodurch es schwierig wird, programmatisch festzustellen, ob die beiden URIs identisch sind.

0

Vielleicht es so versuchen?

from urlparse import urlparse 

websites = set() 

def is_unique(website): 
    # Strip of the last bit 
    parsed = urlparse(website) 
    url = parsed.hostname + parsed.path 
    if url in websites: 
     return False 
    websites.add(url) 
    return True 
Verwandte Themen