0x01 Graphviz简述
Graphviz是大名鼎鼎的贝尔实验室的几位牛人开发的一个画图工具,它提供了“所想即所得”的理念,通过dot语言来编写脚本并绘制图形,简单易懂。
官网:http://www.graphviz.org/
摘自维基百科的资料:https://zh.wikipedia.org/wiki/Graphviz
Graphviz由一种被称为DOT语言的图形描述语言 与一组可以生成和/或处理DOT文件的工具组成:
dot
一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript,PDF,SVG,PNG,含注解的文本等等。
neato
用于sprint model的生成(在Mac OS版本中称为energy minimized)。
twopi
用于放射状图形的生成
circo
用于圆形图形的生成。
fdp
另一个用于生成无向图的工具。
dotty
一个用于可视化与修改图形的图形用户界面程序。
0x02 Graphviz能用来做什么
如果你想做数据分析,或者可视化处理,亦或是想在编程时动态的输出流程图,Graphvizs是一个好帮手。
文字描述就不多说了,主要看下面这些图:
0x03 为什么要用它?
用VISIO、excel、diagram这些工具不方便处理动态生成的流程图,不方便script kids去处理数据结果,经常要导入到这些静态分析的工具中
用html+js+css的方法可以处理,但是编程有十分麻烦,要考虑布局;又由于大部分的js脚本在处理绘图时要接收json格式的数据,处理起来比较麻烦。
但是Graphviz是支持所想即所得,他用图概念中的dot(节点)和edge(边)的概念来处理流程图。是高度封装好的(图类)(我这么理解的)
Graphviz使用的是dot语言,不过没关系,这种语言十分易懂。
dot语言:
片段代码1
1: digraph abc{
2: node [shape="record"];
3: edge [style="dashed"];
4:
5: a [style="filled", color="black", fillcolor="chartreuse"];
6: b;
7: c;
8: d;
9:
10: a -> b;
11: b -> d;
12: c -> d [color="red"];
13: }
片段代码2
strict digraph {
graph [epsilon=0.001];
a -> b;
b -> c;
}
代码中定义边的长度 颜色 由哪个点到哪个点就可以绘制简单的图形了。
如果还嫌麻烦,python 对graphviz 进行了一次封装 使用pygraphviz就可以在python里面直接绘图啦,灰常贴心。
python 代码片段
import pygraphviz as pgv
A=pgv.AGraph()
A.add_edge(1,2)
A.add_edge(2,3)
A.add_edge(1,3)
print(A.string()) # print to screen
print("Wrote simple.dot")
A.write('simple.dot') # write to simple.dot
B=pgv.AGraph('simple.dot') # create a new graph from file
B.layout() # layout with default (neato)
B.draw('simple.png') # draw png
print("Wrote simple.png")
0x04 用Graphviz能做什么
对于网络安全来说,对时间的爆发,攻击的统计,攻击过程还原等等,这种需要在时间顺序中找出攻击规律,或者数据规律的地方是非常有用的。
比如对于一次攻击时间的还原,对于风控中盗号流程的还原。绘图给专家去观察事件爆发的先后顺序,再采用数据统计,或者先后验概率的归类方法,能够让分析者清晰的看到时间发生的前后情况。
0x05 HOW TO GET IT(安装方法)
Windows:
不建议用WINDOWS环境操作,python 可能会找不到Lib库,但是如果你只想用Graphviz那么Windows也是支持的,只是不再维护了,仍然可以下到msi的版本。
到官网下载http://www.graphviz.org/ windows版本的msi文件即可
Linux:
Step1:下载Graphviz http://www.graphviz.org/
tar -zxvf xxxxxxx.tar.gz
python setup.py install
ubuntu可以直接apt-get install graphviz 和graphviz-dev
graphviz-dev是和Python库链接用的,需要下载
Step2:
pygraphviz下载:
方法1:可以到github下载源码也可以到pygraph官网去下载。https://github.com/pygraphviz/pygraphviz
下载后
安装
安装过程中可能会报错,可以尝试安装
sudo apt-get install python-dev
方法2:
片段代码1
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.html
http://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/
直接pip install安装
上述安装方法是在博客看到的,但是可能因为操作系统原因失败了,还是pip好
sudo pip install pygraphviz --install-option="--include-path=/usr/include/graphviz" --install-option="--library-path=/usr/lib/graphviz/"
*************************************************************************************************************************************************
附录:
以下是摘自其他博客的内容,非常有价值:
Graphviz 适合编程快速绘制流程图之类的图形。
而pygraphviz对graphviz进行了封装,提供python程序调用接口。网上有很多对graphiviz进行python封装的程序如pydot等等,个人觉得pygraphviz比较好用,有好的文档和示例程序。https://networkx.lanl.gov/trac/browser/pygraphviz/
在ubuntu下面安装 graphviz
sudo apt-get install graphviz, graphviz-dev
注意graphiviz-dev是pygraphviz所依赖的必须安装。
安装pygraphviz
注意不要sudo apt-get了,因为这样安装的不是最新版本,程序运行会有问题。
到这个地址下载最新的pygraphviz-0.99.1.tar.gz (md5)
http://pypi.python.org/pypi/pygraphviz/
解压缩,然后 sudo python2.6 setup.py install即可。
下面给个例子,如何利用graphiviz 的布局绘制下面的图形呢:
1
//
s.dot
2
//
dot s.dot -Tpng -o s.png -Gsplines=line
3
digraph G {
4
//
a -> c;
5
a
->
b;
6
b
->
c;
7
subgraph x{
8
rank
=
same;
9
b
->
d;
10
}
11
subgraph y{
12
//
rank = same;
13
d
->
e;
14
}
15
subgraph z{
16
rank
=
same;
17
c
->
e;
18
}
19
20
}
21
这里解释下,默认的图布局是自上到下的,TD,当然你可以改成自左向右布局,
digraph G {
rankdir=LR;
.....
}
但是一个时刻只能有一种布局方式,例如上图是采用从上到下的布局方式,为了使得边b->d能够水平,需要采用
subgraph 的方法添加子图,同时说明rank=same.
dot s.dot -Tpng -o s.png -Gsplines=line 中-Gsplines=line 表示强迫边是直线.
http://www.graphviz.org/mywiki/FaqBalanceTree
1
digraph G {
2
a
->
b0
3
xb [label
=
""
,width
=
.
1
,style
=
invis]
4
a
->
xb [style
=
invis]
5
a
->
b1
6
{rank
=
same b0
->
xb
->
b1 [style
=
invis]}
7
b0
->
c0
8
xc [label
=
""
,width
=
.
1
,style
=
invis]
9
b0
->
xc [style
=
invis]
10
b0
->
c1
11
{rank
=
same c0
->
xc
->
c1 [style
=
invis]}
12
}
下面给出利用pygrahviz进行二叉树的绘制
首先给出最简单的绘制,然后是按照上面提到的利用invis属性,构造不可见的顶点和边强迫产生较合适的位置。
a
|
b0—t--b1 原理如昨图所示,对照上面的图示a到b0,a到b1是实边,t为不可见点,a到t,b0到t,t到b1都是不可见边,
这样强迫布局的时候对于横坐标,a尽量在b0,b1的中间。
1.不采用不可见点,边的二叉树绘制效果
1 #printTreeOld.py
2
import pygraphviz
as
pgv
3
4
A
=
pgv.AGraph(directed
=
True,strict
=
True)
5
A.add_edge(
1
,
2
)
6
A.add_edge(
1
,
3
)
7
A.add_edge(
2
,
4
)
8
A.add_edge(
2
,
5
)
9
A.add_edge(
5
,
6
)
10
A.add_edge(
5
,
7
)
11
A.add_edge(
3
,
8
)
12
A.add_edge(
3
,
9
)
13
A.add_edge(
8
,
10
)
14
A.add_edge(
8
,
11
)
15
A.graph_attr[
'
epsilon
'
]
=
'
0.001
'
16
print A.
string
() # print dot file to standard output
17
A.write(
'
fooOld.dot
'
)
18
A.layout(
'
dot
'
) # layout with dot
19
A.draw(
'
fooOld.png
'
) # write to file
2.采用不可见点,边,绘制二叉树的效果,感觉稍微好一点,更像二叉树了:)
下面的代码仅仅是示例,可以提出子函数简化代码。
1
import pygraphviz
as
pgv
2
# strict (no parallel edges)
3
# digraph
4
# with attribute rankdir
set
to
'
LR
'
5
A
=
pgv.AGraph(directed
=
True,strict
=
True)
6
A.add_edge(
1
,
2
)
7
A.add_edge(
1
,
3
)
8
A.add_node(
'
a
'
,style
=
'
invis
'
)
9
A.add_edge(
1
,
'
a
'
,style
=
'
invis
'
)
10
B
=
A.add_subgraph([
2
,
3
,
'
a
'
],rank
=
'
same
'
)
11
B.add_edge(
2
,
'
a
'
,style
=
'
invis
'
)
12
B.add_edge(
'
a
'
,
3
,style
=
'
invis
'
)
13
14
A.add_edge(
2
,
4
)
15
A.add_edge(
2
,
5
)
16
A.add_node(
'
b
'
,style
=
'
invis
'
)
17
A.add_edge(
2
,
'
b
'
,style
=
'
invis
'
)
18
C
=
A.add_subgraph([
4
,
5
,
'
b
'
],rank
=
'
same
'
)
19
C.add_edge(
4
,
'
b
'
,style
=
'
invis
'
)
20
C.add_edge(
'
b
'
,
5
,style
=
'
invis
'
)
21
22
A.add_edge(
5
,
6
)
23
A.add_edge(
5
,
7
)
24
A.add_node(
'
c
'
,style
=
'
invis
'
)
25
A.add_edge(
5
,
'
c
'
,style
=
'
invis
'
)
26
D
=
A.add_subgraph([
6
,
7
,
'
c
'
],rank
=
'
same
'
)
27
D.add_edge(
6
,
'
c
'
,style
=
'
invis
'
)
28
D.add_edge(
'
c
'
,
7
,style
=
'
invis
'
)
29
30
A.add_edge(
3
,
8
)
31
A.add_edge(
3
,
9
)
32
A.add_node(
'
d
'
,style
=
'
invis
'
)
33
A.add_edge(
3
,
'
d
'
,style
=
'
invis
'
)
34
E
=
A.add_subgraph([
8
,
9
,
'
d
'
],rank
=
'
same
'
)
35
E.add_edge(
8
,
'
d
'
,style
=
'
invis
'
)
36
E.add_edge(
'
d
'
,
9
,style
=
'
invis
'
)
37
38
A.add_edge(
8
,
10
)
39
A.add_edge(
8
,
11
)
40
A.add_node(
'
e
'
,style
=
'
invis
'
)
41
A.add_edge(
8
,
'
e
'
,style
=
'
invis
'
)
42
F
=
A.add_subgraph([
10
,
11
,
'
e
'
],rank
=
'
same
'
)
43
F.add_edge(
10
,
'
e
'
,style
=
'
invis
'
)
44
F.add_edge(
'
e
'
,
11
,style
=
'
invis
'
)
45
46
47
A.graph_attr[
'
epsilon
'
]
=
'
0.001
'
48
print A.
string
() # print dot file to standard output
49
A.write(
'
foo.dot
'
)
50
A.layout(
'
dot
'
) # layout with dot
51
A.draw(
'
foo.png
'
) # write to file
52
*************************************************************************************************************************************************
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.html
http://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/
片段代码1
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.html
http://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/