Python 3:如何从嵌套列表生成 table 作为输入

Python 3: How to generate a table from a nested list as input

所以,我得到了以下嵌套列表(我从 Nmap XML 输出文件中解析出来的)。它基本上是 IP 地址及其所有开放端口的列表:

[['192.168.23.78', ['53', '88', '135', '139', '389', '445', '3389']],
 ['192.168.27.243', ['135', '139', '445', '3389', '5800', '5900']],
 ['192.168.99.164', ['135', '139', '445', '3389', '5800', '5900']],
 ['192.168.228.211', ['80']],
 ['192.168.171.74', ['135', '139', '445', '3389', '5800', '5900']]]

我想根据此数据创建一个 table,其中每个第一项(所有 IP 地址)都打印为行。然后我希望遍历每个第二项(每个 IP 地址的所有端口的列表),并计算每个唯一的端口号。我希望这个新计算的唯一端口列表打印为我的 table 的列 headers。我的空 table 应该大致如下所示:

                 53  80  88  135  139  389  445  3389  5800  5900
192.168.23.78
192.168.27.243
192.168.99.164
192.168.228.211
192.168.171.74

然后我希望在具有给定开放端口的每个 IP 地址的每个正确单元格中放置 X,如下所示:

                 53  80  88  135  139  389  445  3389  5800  5900
192.168.23.78    X   X       X    X    X         X
192.168.27.243               X    X         X    X     X     X
192.168.99.164               X    X         X    X     X     X
192.168.228.211      X
192.168.171.74               X    X         X    X     X     X

我将如何处理我的数据集?

我完全是个新手,但我可能会想出如何遍历所有端口号并获得唯一的端口列表。但我完全不知道如何在正确的单元格

中绘制 table 上的 X

到目前为止,这是我的代码:

#!/usr/bin/env python

from pprint import pprint
import xml.etree.ElementTree as ET

def loopy(item):
    for port in host.findall('ports/port'):
        if port.get('protocol') == "tcp":
            portid = port.get('portid')
            for state in port.findall('state'):
                if state.get('state') == "open":
                    if item == "address":
                        list_addr.append(addr)
                        return
                    elif item == "portid":
                        list_portid.append(portid)

root = ET.parse('scan5.xml').getroot()
result = []
for host in root.findall('host'):
    list_portid = []
    list_addr = []
    address = host.find('address')
    addr = address.get('addr')
    loopy("address")
    loopy("portid")
    if list_addr:
        result.append([list_addr[0], list_portid])

pprint(result)

我的嵌套列表现在在 result 中,但我不知道如何从中创建 table。

到目前为止我的代码只生成原始列表:

[['10.133.23.78', ['53', '88', '135', '139', '389', '445', '3389']],
 ['10.133.27.243', ['135', '139', '445', '3389', '5800', '5900']],
 ['10.133.99.164', ['135', '139', '445', '3389', '5800', '5900']],
 ['10.135.228.211', ['80']],
 ['10.133.171.74', ['135', '139', '445', '3389', '5800', '5900']]]

你可以使用安装和使用 prettytable 包来可视化 pretty table

第一pip install prettytable

然后代码

from prettytable import PrettyTable

data = [['192.168.23.78', ['53', '88', '135', '139', '389', '445', '3389']],
        ['192.168.27.243', ['135', '139', '445', '3389', '5800', '5900']],
        ['192.168.99.164', ['135', '139', '445', '3389', '5800', '5900']],
        ['192.168.228.211', ['80']],
        ['192.168.171.74', ['135', '139', '445', '3389', '5800', '5900']]]

ports = sorted(set([int(port) for _, open_ports in data for port in open_ports]))

my_table = PrettyTable()
header = ['ip']
header.extend(ports)
my_table.field_names = header
for ip_address, open_ports in data:
    row = [ip_address]
    row.extend('X' if str(port) in open_ports else '' for port in ports)
    my_table.add_row(row)

print(my_table)

输出

+-----------------+----+----+----+-----+-----+-----+-----+------+------+------+
|        ip       | 53 | 80 | 88 | 135 | 139 | 389 | 445 | 3389 | 5800 | 5900 |
+-----------------+----+----+----+-----+-----+-----+-----+------+------+------+
|  192.168.23.78  | X  |    | X  |  X  |  X  |  X  |  X  |  X   |      |      |
|  192.168.27.243 |    |    |    |  X  |  X  |     |  X  |  X   |  X   |  X   |
|  192.168.99.164 |    |    |    |  X  |  X  |     |  X  |  X   |  X   |  X   |
| 192.168.228.211 |    | X  |    |     |     |     |     |      |      |      |
|  192.168.171.74 |    |    |    |  X  |  X  |     |  X  |  X   |  X   |  X   |
+-----------------+----+----+----+-----+-----+-----+-----+------+------+------+

使用 numpypandas 你可以做到

import pandas as pd
import numpy as np

table = [['192.168.23.78', ['53', '88', '135', '139', '389', '445', '3389']],
         ['192.168.27.243', ['135', '139', '445', '3389', '5800', '5900']],
         ['192.168.99.164', ['135', '139', '445', '3389', '5800', '5900']],
         ['192.168.228.211', ['80']],
         ['192.168.171.74', ['135', '139', '445', '3389', '5800', '5900']]]

# Collect the ip_addresses
ip_addresses = [el[0] for el in table]

# Collect the column names. Temporarily convert to integers to sort them properly
columns = sorted(np.unique([c for el in table for c in el[1]]), key = lambda x: int(x))


# Initialize numpy matrix to hold strings
table_matrix = np.zeros((len(ip_addresses), len(columns)), str)

for row in table:
    # Get the row index of the IP address
    for i, ip in enumerate(ip_addresses):
        if row[0] == ip:
            rdx = i
    # Check which columns have values in the row that corresponds to the IP address    
    for c in row[1]:
        for j, col in enumerate(columns):
            # Add an X if the row has that column
            if c == col:
                table_matrix[rdx, j] = 'X'

# Create DataFrame
df = pd.DataFrame(table_matrix, index = ip_addresses, columns = columns)

输出:

Out[24]: 
                53 80 88 135 139 389 445 3389 5800 5900
192.168.23.78    X     X   X   X   X   X    X          
192.168.27.243             X   X       X    X    X    X
192.168.99.164             X   X       X    X    X    X
192.168.228.211     X                                  
192.168.171.74             X   X       X    X    X    X