2012-03-24 6 views
1

두 개 이상의 URL이 중복 된 경우 아래 코드와 같은 몇 가지 추가 매개 변수가 있는지 확인하는 가장 좋은 방법을 찾고 있습니다. fac에서 url1과 url2는 동일하지만 webspider를 실행하면 두 개의 별도 URL로 취급되어 결과가 중복됩니다.Python에서 중복 된 URL을 확인하는 가장 좋은 방법은 무엇입니까?

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' 

은 즉, 나는 그것을 중복 또는하지 않을 경우 내가 확인할 수 있습니다 새 URL을 크롤링 할 때 다음 다음 데이터베이스에 저장할 경우, url 헤더를 사용하여 MD5 해시를 생성합니다. 하지만 파이썬에서이 작업을하는 가장 좋은 방법인지는 잘 모르겠습니다.

는 두 URI를 둘 다 검색하지 않고 동일한 자원을 가리 여부를 알 수있는 방법은 없습니다

답변

3

웹 페이지의 결과는 '추가 매개 변수'에 따라 동일하거나 다를 수 있습니다. 따라서 일반적으로 URL을 보면 중복 콘텐츠를 탐지하는 규칙을 정의 할 수 없습니다.

나는 url1과 url2를 different.Compute로하여 각 블록의 md5sum을 URL로부터받은 1024 단어로 처리하도록 제안합니다. 중복을 탐지 할 수 있도록 이러한 md5sum의 해시 맵을 유지 관리합니다.

아마도일부는 필요한 기능 중 일부를 제공 할 수 있습니다.


OP의 의견을 바탕으로 업데이트 : 내 대답을 향상시키기위한 몇 가지 코드를 작성했습니다. 두 가지 버전이 있습니다 : 첫 번째는 간단하다 : 위의 코드가 예상되는 방법으로 중복을 감지 기대하는 순진했다

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() 

이 : 현재 웹 페이지가 너무 복잡하다. 따라서 사용자의 눈에는 똑같은 두 개의 URL도 실제로 광고, 해시 태그, 자체 URL 이름 포함 등으로 인해 많은 차이가 있습니다.

두 번째 버전은보다 정교합니다. 그것은 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() 

그러나 두 번째 버전 역시 작동하지 않습니다. 이유는 동일합니다. 사실 두 URL의 헤드 텍스트의 차이는 포함 된 해시 값이었고 두 URL의 본문 텍스트 간의 차이는 webhp 문자열이었습니다. difflib.context_diff를 사용하여 차이를 계산했습니다.

웹 페이지를 더 지능적으로 구문 분석하고 더 지능적으로 diff를 계산하는 세 번째 버전을 포함하도록 코드를 향상시킬 수 있습니다. 예를 들어, < 5 % diff (이 비율은 difflib 함수를 사용하여 쉽게 계산할 수 있음)의 텍스트도 복사하여 선언합니다.

+0

안녕하세요. 대답 해 주셔서 감사합니다. "md5sums의 해시 맵을 유지 관리하여 중복을 탐지 할 수 있도록"대한 자세한 팁을 알려주십시오. 사실, 나는 부끄러운 것을 배웠지 만, 현재의 프로젝트에서는 상당히 복잡합니다. – mrblue

1

대단히 감사합니다. 근본적으로 동일한 콘텐츠 일지라도 어쨌든 각 요청에 따라 변경되는 광고와 같은 동적 요소가있어 프로그래밍 방식으로 두 URI가 동일한 지 여부를 감지하기 어렵습니다.

0

어쩌면 이렇게 해보시겠습니까?

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 
관련 문제