2017-12-06 3 views
1

辞書を使用してPythonでWebリンクの大きなツリーを保存するプログラムを作成しています。基本的には、ルートURLから始まり、ルートのHTMLから見つかったURLに基​​づいて辞書を作成します。次のステップでは、これらのURLのそれぞれのページを取得し、それらのURLのリンクを取得したいと考えています。最終的には、その中のすべてのリンクと、それらのリンクとの関係を持つ辞書が必要です。Pythonで辞書に自動的にレイヤーを追加する

これは、このシステムが動作する最初の二つの深さのために私が持っているもの

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を1つずつクロールし、そのページにあるすべてのURLを1つずつクロールするなどの基本的な例...また、見つかったすべてのURLを表示します。

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の親、その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_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

これをまさに私が探しているものです!もともと、Webページに再帰関数を使用することを考えていましたが、どうやってURLを追跡するかわかりませんでした。私はこの[投稿](https://stackoverflow.com/questions/19937210/dynamically-set-deep-python-dict)を見ましたが、それを私のプログラムに跳躍させる方法についてはわかりませんでした。ご協力いただきありがとうございます! – SheepyBloke

関連する問題