首页 > 解决方案 > 将 HTML 结构转换为网络图

问题描述

我要做的是将 HTML 站点 DOM(文档对象模型)表示为网络图,然后用该图进行一些统计计算(如度数、介数、接近度、绘图等)。我找不到任何直接执行此操作的库或以前的 SO 帖子。我的想法是使用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'))

在此处输入图像描述

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

PS:图表可以是定向的,也可以不是定向的,我不在乎。

标签: pythondomgraphbeautifulsoupnetworkx

解决方案


您可以遍历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()

在此处输入图像描述


推荐阅读