简体   繁体   English

通过networkx并使用python在图中添加节点和边

[英]Add nodes & edges in graph via networkx and using python

I need to create a graph of IP addresses and mark edges between them for which I wrote the code below. 我需要创建一个IP地址图,并在它们之间标记边缘,我为此编写了以下代码。 The list, content of the parseOutput(), looks something like this : 该列表是parseOutput()的内容,看起来像这样:

('172.16.254.128', '216.58.208.206')
('216.58.208.206', '172.16.254.128')
('172.16.254.128', '216.58.208.226')
('216.58.208.226', '172.16.254.128')
('172.16.254.128', '8.8.8.8')
('8.8.8.8', '172.16.254.128')
('172.16.254.128', '216.58.208.227')
('172.16.254.128', '216.58.208.227')
('216.58.208.227', '172.16.254.128')
('172.16.254.128', '216.58.208.227')
('172.16.254.128', '216.58.208.227')
...

when I run this code, I get the following error: 运行此代码时,出现以下错误:

Traceback (most recent call last):
  File "test.py", line 40, in <module>
    g.add_nodes_from(nodeList)
  File "/usr/local/lib/python2.7/dist-packages/networkx/classes/graph.py", line 429, in add_nodes_from
    nn,ndict = n
ValueError: need more than 0 values to unpack

import logging, sys, struct, binascii, socket
from scapy.all import *
import networkx as nx
import matplotlib.pyplot as plt

pkts=rdpcap("pcapFile.pcap",20)

def parsePcap():
        IPList = [[] for i in range (20)]
        count = 0
        for pkt in pkts:
                #print pkt.summary()
                if pkt.haslayer(IP):
                        #proto = pkt.getLayer(IP).proto
                        x = pkt.getlayer(IP).src
                        y = pkt.getlayer(IP).dst
                        IPList[count]= (x,y)
                        #IPList[count].append(proto)
                        print IPList[count]
                        count += 1
        return IPList


parseOutput = parsePcap()
nodeList = parseOutput
edgeList = parseOutput

g = nx.Graph()

g.add_nodes_from(nodeList)
print g.number_of_nodes
g.add_edges_from(edgeList)

pos = nx.spring_layout(g,scale=1) #default to scale=1
nx.draw(g,pos)

I dont' even know what I'm doing wrong. 我什至不知道我在做什么错。 The documentation doesn't tell much and all examples online seem to be written in the same syntaxt as my code. 该文档并没有提供太多信息,所有在线示例似乎都使用与我的代码相同的语法编写。

The problem you are seeing is caused by 您看到的问题是由引起的

IPList = [[] for i in range (20)]

which leads to parsePcap() returning a list of sequences with an empty list or lists at the end when len(pkts) is less than 20: len(pkts)小于20时,导致parsePcap()返回序列列表,列表的末尾为空:

parseOutput = [
('172.16.254.128', '216.58.208.206'),
...
('172.16.254.128', '216.58.208.227'),
[],  #<---------------- This is causing the problem 
]

When parseOutput is passed to g.add_nodes_from , you get the traceback error message: parseOutput传递给g.add_nodes_from ,您将得到追溯错误消息:

File "/usr/local/lib/python2.7/dist-packages/networkx/classes/graph.py", line 429, in add_nodes_from
  nn,ndict = n
ValueError: need more than 0 values to unpack

In retrospect, if you think carefully about the error message you can see it is telling you that n has 0 values to unpack. 回想起来,如果您仔细考虑错误消息,您会发现它告诉您n有0个要解压的值。 That makes sense if n , the node, is an empty list: 如果节点n为空列表,这是有道理的:

In [136]: nn, ndict = []
ValueError: need more than 0 values to unpack

The empty list is coming from parseOutput . 空列表来自parseOutput


Instead of pre-allocating a list of a fixed size: 而不是预先分配固定大小的列表:

IPList = [[] for i in range (20)]

the preferred way to do this in Python is to use the append method: 在Python中执行此操作的首选方法是使用append方法:

def parsePcap():
    IPList = []
    for pkt in pkts:
        if pkt.haslayer(IP):
            x = pkt.getlayer(IP).src
            y = pkt.getlayer(IP).dst
            IPList.append((x, y))
    return IPList

This is easier and more readable, since you do not need to fuss with index numbers and increment a counter variable. 因为您不必大惊小怪地使用索引号和增加计数器变量,所以这更容易且更具可读性。 Moreover, it allows you to handle an arbitrary number of items in pkts without first having to know the length of pkts . 此外,它使您可以先处理pkts的任意数量的项目,而不pkts知道pkts的长度。


Another thing that needs to be fixed is that the nodeList typically is not the same as the edgeList . 需要修复的另一件事是, nodeList通常与edgeList

If you are going to declare a nodeList , the nodeList should be an iterable of IP addresses, and the edgeList should be an iterable of tuples, like parseOutput : 如果要声明一个nodeList ,则nodeList应该是IP地址的可迭代对象,而edgeList应该是元组的可迭代对象,例如parseOutput

nodeList = set([item for pair in parseOutput for item in pair])
print(nodeList)
# set(['216.58.208.206', '216.58.208.227', '172.16.254.128',
#  '216.58.208.226', '8.8.8.8'])

However, since all your nodes are also mentioned in edgeList, you can omit declaring the nodes and just use 但是,由于在edgeList中也提到了所有节点,因此可以省略声明节点,而只需使用

edgeList = parseOutput
g.add_edges_from(edgeList)

g.add_edges_from will add the nodes implicitly. g.add_edges_from将隐式添加节点。


import matplotlib.pyplot as plt
import networkx as nx

parseOutput = [
('172.16.254.128', '216.58.208.206'),
('216.58.208.206', '172.16.254.128'),
('172.16.254.128', '216.58.208.226'),
('216.58.208.226', '172.16.254.128'),
('172.16.254.128', '8.8.8.8'),
('8.8.8.8', '172.16.254.128'),
('172.16.254.128', '216.58.208.227'),
('172.16.254.128', '216.58.208.227'),
('216.58.208.227', '172.16.254.128'),
('172.16.254.128', '216.58.208.227'),
('172.16.254.128', '216.58.208.227'),]

g = nx.Graph()
edgeList = parseOutput
g.add_edges_from(edgeList)

pos = nx.spring_layout(g,scale=1) #default to scale=1
nx.draw(g,pos, with_labels=True)
plt.show()

yields 产量

在此处输入图片说明


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM