2017-12-06 6 views
1

파이썬에서 웹 링크의 큰 나무를 저장하기 위해 사전을 사용하는 프로그램을 만들고 있습니다. 기본적으로 루트 URL로 시작하면 루트의 HTML에서 찾은 URL을 기반으로 사전을 만듭니다. 다음 단계에서는 각 URL의 페이지를 가져와 해당 URL의 링크를 가져 오려고합니다. 결국, 나는 그것에있는 모든 링크와 서로에 대한 관계를 가진 사전을 갖고 싶습니다. 파이썬에서 자동으로 레이어를 사전에 추가하기

내가이 시스템이 작동 처음 두 깊이

for link in soup.find_all('a'): 
    url = link.get('href') 
    url_tree[siteurl][url] 
#Get page source 
    for link in soup.find_all('a'): 
    url = link.get('href') 
    url_tree[siteurl][secondurl][url] 

위해 가지고,하지만 당신은 말할 수, 나는 블록의 많은으로 가져 N 층 깊이 사전을 원하는 경우 암호. 더 많은 레이어를 자동으로 추가하는 방법이 있습니까? 어떤 도움을 주셔서 감사합니다!

답변

0

이것은 재귀 함수를 사용하여 수행 할 수 있습니다.

페이지에서 발견 된 모든 URL을 하나씩 크롤링 한 다음 해당 페이지에서 찾은 모든 URL을 하나씩 크롤링하는 기본 예제 ... 또한 발견 한 모든 URL을 인쇄합니다.


찾은 모든 URL의 트리의 DICT을 갖고 싶어하기 때문에

def recursive_fetch(url_to_fetch): 
    # get page source from url_to_fetch 
    # make a new soup 
    for link in soup.find_all('a'): 
     url = link.get('href') 
     print url 
     # run the function recursively 
     # for the current url 
     recursive_fetch(url) 


# Usage 
recursive_fetch(root_url) 

은, 위의 코드는 훨씬 도움이되지 않습니다, 그러나 그것은 시작입니다.

이것은 실제로 복잡해집니다. 이제는 현재 URL의 상위 항목 인 크롤링중인 URL, 해당 URL의 상위 항목, 상위 항목의 상위 항목, 상위 항목의 상위 항목, 하위 항목 등을 추적해야하기 때문에 ...

평균? 그것은 매우 복잡하고 매우 빠릅니다.

다음은이 모든 것을 수행하는 코드입니다. 내가 할 수있는 한 최선을 설명하기 위해 코드에 주석을 썼다. 그러나 재귀 함수가 더 나은 이해를 위해 어떻게 작동하는지 실제로 이해해야합니다. 과 같이 표시됩니다

def get_parent(tree, parent_list): 
    """How it works: 

    Let's say the `tree` looks like this: 

     tree = { 
      'root-url': { 
       'link-1': { 
        'link-1-a': {...} 
       } 
      } 
     } 

    and `parent_list` looks like this: 

     parent_list = ['root-url', 'link-1', 'link-1-a'] 

    this function will chain the values in the list and 
    perform a dict lookup like this: 

     tree['root-url']['link-1']['link-1-a'] 
    """ 

    first, rest = parent_list[0], parent_list[1:] 
    try: 
     if tree[first] and rest: 
      # if tree or rest aren't empty 
      # run the function recursively 
      return get_parent(tree[first], rest) 
     else: 
      return tree[first] 
    except KeyError: 
     # this is required for creating the 
     # root_url dict in the tree 
     # because it doesn't exist yet 

     tree[first] = {} 
     return tree[first] 

그리고 recursive_fetch 기능 :

먼저, 나무에서 URL의 부모를 얻기에 매우 도움이 될 것입니다 다른 함수를 살펴 보자

url_tree = {} # dict to store the url tree 


def recursive_fetch(fetch_url, parents=None): 
    """ 
    `parents` is a list of parents of the current url 
    Example: 
     parents = ['root-url', 'link-1', ... 'parent-link'] 
    """ 
    parents = parents or [] 

    parents.append(fetch_url) 

    # get page source from fetch_url 
    # make new soup object 

    for link in soup.find_all('a'): 
     url = link.get('href') 

     if parents: 
      parent = get_parent(url_tree, parents) 
     else: 
      parent = None 

     if parent is not None: 
      # this will run when parent is not None 
      # i.e. even if parent is empty dict {} 

      # create a new dict of the current url 
      # inside the parent dict 
      parent[url] = {} 
     else: 
      # this url has no parent, 
      # insert this directly in the url_tree 
      url_tree[url] = {} 

     # now crawl the current url 
     recursive_fetch(url, parents) 

    # Next is the most import block of code 
    # Whenever 1 recursion completes, 
    # it will pop the last parent from 
    # the `parents` list so that in the 
    # next recursion, the parents are correct. 
    # Whithout this block, the url_tree wouldn't 
    # look as expected. 
    # It took me many hours to figure this out 

    try: 
     parents.pop(-1) 
    except IndexError: 
     pass 
+0

이를 내가 찾던 바로 그 것이다! 원래 웹 페이지에 재귀 함수를 사용하는 방법을 생각했지만 그 방법을 모르고 URL을 추적했습니다. 나는이 [post] (https://stackoverflow.com/questions/19937210/dynamically-set-deep-python-dict)를 보았지만 그것을 내 프로그램으로 도약시키는 방법에 대해서는 확신하지 못했습니다. 당신의 도움을 주셔서 감사합니다! – SheepyBloke

관련 문제