Python-graphviz模块-使用教程

1 情景引入

前几个月师姐给了个任务——恶意样本行为可视化,输入为xml文件,一个文件代表一个恶意样本。请教学姐学长同学等,加上观看效果图,得出实现思路:python解析xml文件,使用python模块graphviz进行可视化;之后使用图数据库neo4j进行对比。

之后发现neo4j创建多个图数据库比较麻烦,但是按照行为分类等都比较直观,所以做辅助作用应该不错。

图片名称

下面对graphviz进行整理。

2 Graphviz

Graphviz 是一个自动排版的作图软件,可以生成 png pdf 等格式。

3 python graphviz

python graphviz则是graphviz的python实现。我们可以通过python graphviz实现轻松完成各种流程图的绘制。

3.1 安装

  1. 安装python graphviz木块(本机使用的是python3.9):

    1
    pip install graphviz
  2. 除了python安装外,本机还需要安装Graphviz(下载页面),并确保包含dot可执行文件的目录在系统路径上。安装过程中需要添加PATH:

    图片名称

    否则出现下面的报错:(重启Pycharm生效)

    1
    graphviz.backend.execute.ExecutableNotFound: failed to execute WindowsPath('dot'), make sure the Graphviz executables are on your systems' PATH

    graphviz.backend.ExecutableNotFound: failed to execute [‘dot’, ‘-Tpng’, ‘-O’, ‘t est.gv’]问题解决方法

    解决报错:添加环境变量

    图片名称

3.2 使用

该graphviz模块提供了两个类:Graph和 Digraph。它们分别以DOT语言为无向图和有向图创建图描述。它们具有相同的 API。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from graphviz import Digraph

dot = Digraph(comment='恶意样本行为可视化', format='jpg')

# 初始化端点
dot.node(name='n1', label='端点A', color="#008000", fontcolor="#000000", style="filled", shape="rectangle", fontname="Microsoft YaHei")
dot.node(name='n2', label='端点B', color="#FFD700", fontcolor="#000000", style="filled", shape="circle", fontname="Microsoft YaHei")
dot.node(name='n3', label='端点C', color="#0000FF", fontcolor="#FFFFFF", style="filled", shape="oval", fontname="Microsoft YaHei")

# 布局 L-左 R-右 T-上 B-下
dot.attr(rankdir='LR') # 自左向右
# dot.attr(rankdir='RL')
# dot.attr(rankdir='TB') # 默认
# dot.attr(rankdir='BT')
# 初始化边
dot.edge('n1', 'n2', label="边1", color="#000000", fontcolor="#000000", style="", fontname="Microsoft YaHei")
dot.edge('n1', 'n3', label="边2", color="#FF0000", fontcolor="#FF0000", style="dashed", fontname="Microsoft YaHei")

# 保存文件,view=False时将不自动打开文件
# dot.render("test_graphviz.gv", format='jpg', view=True)
# 不保存文件,仅仅自动打开
u = dot.unflatten(stagger=1)
u.view()

显示如下:

图片名称

3.3 中文乱码

如果出现中文乱码,多半是因为没有设置fontname为支持中文显示的字体,只需要在node或者edge中添加fontname="Microsoft YaHei",即可正常显示。

3.4 端点、边、字体颜色

在node或者edge中添加color="#000000", fontcolor="#000000"即可,具体颜色可以参考:

3.5 端点的形状

在node中添加shape="xxx"即可,具体需要什么形状可以在官网中查找。

3.6 Rank

GraphViz DOT有向图 (四)node节点布局控制之rank,group,subgraph

3.7 排版

如上面的示例,使用dot.attr(rankdir='xx')来确定排版,作用范围为使用该行代码之后,下一个dot.attr(rankdir='xx')代码之前。

3.8 name参数中不能有英文冒号

1
2
3
dot.node(name='n1', label='n1')
dot.node(name='n2:3', label='n2:3')
dot.edge('n1', 'n2:3')

dot.node(name="xxx") 如果name参数含有英文逗号,则会报错,导致画图错误:

1
Warning: node n2, port 3 unrecognized

常见的思路是使用python将name参数改成中文冒号,label参数是原来的英文冒号,达到正确显示的目的。

1
2
3
string = "http://gsstudio.info/panel"
label = repr(string)
name = repr(string.replace(":", ":"))

repr函数是防止字符串转义的,详细见博客——python中防止字符串转义

3.9 报错:graphviz.backend.execute.CalledProcessError

报错信息:

1
2
3
subprocess.CalledProcessError: Command '[WindowsPath('dot'), '-Kdot', '-Tjpg', '-O', '57630-0.xml.gv']' returned non-zero exit status 3221225477.
...
graphviz.backend.execute.CalledProcessError: Command '[WindowsPath('dot'), '-Kdot', '-Tjpg', '-O', '57630-0.xml.gv']' returned non-zero exit status 3221225477. [stderr: b'dot: graph is too large for cairo-renderer bitmaps. Scaling by 0.876568 to fit\r\n']

现象:

.gv文件可以正常生成,图片文件.jpg无法生成。

定位报错语句:

1
2
3
dot = Digraph(comment='恶意样本行为可视化', format='jpg')
...
dot.render(output_dir + "\\" + file_name + ".gv", format='jpg')

原因:

生成的graph太大,dot无法导出,换成pdfsvg就可以了,pngjpg都不行。

最后选择pdf格式,因为导出的文件小。

1
2
3
dot = Digraph(comment='恶意样本行为可视化', format='pdf')
...
dot.render(output_dir + "\\" + file_name + ".gv", format='pdf')
图片名称

X 参考