代码之家  ›  专栏  ›  技术社区  ›  agenis

网络图中的HTML结构

  •  3
  • agenis  · 技术社区  · 6 年前

    我要做的是将一个HTML站点DOM(文档对象模型)表示成一个网络图,然后用这个图做一些统计计算(如度、中间度、邻近度、当然是绘图等)。我找不到任何图书馆或以前的,所以直接贴。我的想法是用 BeautifulSoup 图书馆 Networkx 图书馆。我试图在HTML结构的每个元素中编写一些代码循环(使用 recursive=True )但是我不知道如何识别每一个唯一的标签(你在这里看到的是添加一秒钟 h1 节点到图中会覆盖第一个节点,对于父节点也是如此,因此图最后是完全错误的)。

    import networkx as nx
    import bs4
    from bs4 import BeautifulSoup
    ex0 = "<html><head><title>Are you lost ?</title></head><body><h1>Lost on the Intenet ?</h1><h1>Don't panic, we will help you</h1><strong><pre>    * <----- you are here</pre></strong></body></html>"
    soup = BeautifulSoup(ex0)
    G=nx.Graph()
    for tag in soup.findAll(recursive=True):
        G.add_node(tag.name)
        G.add_edge(tag.name, tag.findParent().name)
    nx.draw(G)   
    G.nodes
    #### NodeView(('html', '[document]', 'head', 'title', 'body', 'h1', 'strong', 'pre'))
    

    enter image description here

    关于如何完成的任何想法(包括完全不同的方法)。谢谢

    附言:这张图是否可以定向,我不在乎。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Ajax1234    6 年前

    你可以循环 content 每个的属性 BeautifulSoup 对象。要显示标签,只需使用 with_labels 属性 nx.draw :

    import networkx as nx
    import matplotlib.pyplot as plt
    from collections import defaultdict
    from bs4 import BeautifulSoup as soup
    ex0 = "<html><head><title>Are you lost ?</title></head><body><h1>Lost on the Intenet ?</h1><h1>Don't panic, we will help you</h1><strong><pre>    * <----- you are here</pre></strong></body></html>"
    d = soup(ex0, 'html.parser')
    def _traverse_html(_d:soup, _graph:nx.Graph, _counter, _parent=None) -> None:
      for i in _d.contents:
         if i.name is not None:
           try:
             _name_count = _counter.get(i.name)
             if _parent is not None:
               _graph.add_node(_parent)
               _graph.add_edge(_parent, i.name if not _name_count else f'{i.name}_{_name_count}')
             _counter[i.name] += 1
             _traverse_html(i, _graph, _counter, i.name)
           except AttributeError:
             pass
    
    _full_graph = nx.Graph()
    _traverse_html(d, _full_graph, defaultdict(int))
    nx.draw(_full_graph, with_labels = True)   
    plt.show()
    

    enter image description here