2013-06-18 2 views
0

현재 거미 작업을하고 있습니다.파이썬에서 여러 값을 반환하는 방법

import httplib, sys, re 

def spider(target, link): 
     try: 
     conn = httplib.HTTPConnection(target) 
     conn.request("GET", "/") 
     r2 = conn.getresponse() 
     data = r2.read().split('\n') 
     for x in data[:]: 
      if link in x: 
       a=''.join(re.findall("href=([^ >]+)",x)) 
       a=a.translate(None, '''"'"''') 
       if a: 
        return a 
    except: 
     exit(0) 

print spider("www.yahoo.com", "http://www.yahoo.com") 

하지만 난 단지 내가이 모든 링크를 만들 수있는 방법, 출력 1 개 링크를 얻을 :하지만 난 거미() 링크를 따라 한 번 이상 기능, 여기에 내 코드를 호출 할 수 있어야합니다 ?

거미가 링크를 따라갈 수 있도록 어떻게 링크에서 하위 사이트를 얻을 수 있습니까?

+5

힌트 :'yield', 튜플 /리스트 – Doorknob

답변

2

이것은 당신이

import httplib, sys, re 

def spider(link, depth=0): 
    if(depth > 2): return [] 

    try: 
     conn = httplib.HTTPConnection(link) 
     conn.request("GET", "/") 
     r2 = conn.getresponse() 
     data = r2.read().split('\n') 
     links = [] 
     for x in data[:]: 
      if link in x: 
       a=''.join(re.findall("href=([^ >]+)",x)) 
       a=a.translate(None, '"' + "'") 
       if a: 
        links.append(a) 

     # Recurse for each link 
     for link in links: 
      links += spider(link, (depth + 1)) 

     return links 

    except: 
     exit(1) 

print spider("http://www.yahoo.com") 

그것은 검증되지 않은입니다 찾고있는 아마 가까운,하지만 기본이있다. 모든 링크를 다 쳤다가 재귀 적으로 크롤링합니다. 이 함수는 각 호출에서 페이지의 링크 목록을 반환합니다. 그리고 페이지가 재귀 적으로 크롤링되면 재귀 호출에 의해 반환 된 링크가이 목록에 추가됩니다. 코드에는 최대 재귀 깊이가 있기 때문에 영원히 갈 수 없습니다.

주기 감지와 같은 명백한 실수가 없습니다.

몇 가지 부처님께서는 이런 것들을 더 잘 수행 할 수있는 방법이 있습니다.

예를 들어 urllib2은 httplib를 사용하는 것보다 훨씬 쉽게 웹 페이지를 가져올 수 있습니다.

그리고 BeautifulSoup은 regex + translate kluge보다 웹 페이지에서 링크를 더 잘 추출합니다.

+0

나는 그것에 대해 생각했지만 예상되는 반환 값이 무엇인지 확실하지 않았습니다. 찾은 링크의 최상위 목록을 원하지 않는다면 deque는보다 직관적 일 것입니다. – jedwards

+0

위대한, 그냥 내가 뭘 찾고있어! 훌륭한 설명과 조언. – D4zk1tty

+0

와우, 팁을 사용하여 8 행을 만들었습니다! 고마워요. :) – D4zk1tty

0

doorknob의 힌트에 따르면 return ayield a으로 변경하면 기능이 generator이됩니다. 이것을 호출하고 결과를 얻는 대신 반복자를 호출하고 반복자를 돌려 놓습니다. 반복 할 수 있습니다.

if link in x: 
    a=''.join(re.findall("href=([^ >]+)",x)) 
    a=a.translate(None, '''"'"''') 
    if a: 
     yield a 

다음이에 print 문을 변경 :

그래서,이에 if 블록을 변경

for a in spider("www.yahoo.com", "http://www.yahoo.com"): 
    print a 

하면됩니다.

그러나 나는 정말로 원하지 않았다고 생각합니다. joinfindall입니다. 당신은 각각의 "found"것을 분리하여 루프하고 싶었다. 그걸 어떻게 고쳐 주겠어? 쉽고, 단지 re.findall 주위 루프, 루프 당 한 번 yield : 발전기, 반복자는, this presentation을 참조 작업 방법에 대한 자세한 설명은

if link in x: 
    for a in re.findall("href=([^ >]+)",x)): 
     a=a.translate(None, '''"'"''') 
     if a: 
      yield a 

.