您好,我正在重新发布此问题,但提供了有关我要实现的内容的更多信息。在过去的几天里,它一直让我发疯,我似乎无法取得进展。基本上,我有这个数据结构:
data_in =\
{'map': {'command_line': u'command goes here',
'scaninfo': {u'tcp': {'method': u'syn', 'services': u'80,443'}},
'stats': {'downhosts': u'0',
'elapsed': u'1.71',
'timestr': u'Thu Mar 20 18:18:09 2014',
'totalhosts': u'3',
'uphosts': u'3'}},
'scan': {u'2a00:2384:0:208f::13': {'addresses': {u'ipv6': u'2a00:2384:0:f467::13',
u'mac': u'00:gf:88:9:56:D5'},
'hostname': u'static.abc.com',
'status': {'reason': u'nd-response',
'state': u'up'},
u'tcp': {80: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'http',
'product': '',
'reason': u'syn-ack',
'state': u'open',
'version': ''},
443: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'https',
'product': '',
'reason': u'syn-ack',
'script': {u'ssl-cert': u'place holder'},
'state': u'open',
'version': ''}},
'vendor': {u'00:0C:29:7C:13:D3': u'VMware'}},
u'2a00:2384:0:208f::15': {'addresses': {u'ipv6': u'a848:2384:0:3456::15',
u'mac': u'00:gf:29:99:6D:96'},
'hostname': u'static.xyz.com',
'status': {'reason': u'nd-response',
'state': u'up'},
u'tcp': {80: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'http',
'product': '',
'reason': u'syn-ack',
'state': u'open',
'version': ''},
443: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'https',
'product': '',
'reason': u'syn-ack',
'script': {u'ssl-cert': u'place holder'},
'state': u'open',
'version': ''}},
'vendor': {u'00:0C:67:99:6f:96': u'VMware'}},
u'2a00:2384:0:208f::16': {'addresses': {u'ipv6': u'8938:8584:0:8685::16',
u'mac': u'00:54:29:fg:55:0F'},
'hostname': u'static.edf.com',
'status': {'reason': u'nd-response',
'state': u'up'},
u'tcp': {80: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'http',
'product': '',
'reason': u'syn-ack',
'state': u'open',
'version': ''},
443: {'conf': u'3',
'cpe': '',
'extrainfo': '',
'name': u'https',
'product': '',
'reason': u'syn-ack',
'script': {u'ssl-cert': u'place holder'},
'state': u'open',
'version': ''}},
'vendor': {u'00:0C:55:AE:33:ff': u'VMware'}}}}
需要创建一个如下所示的简化版本:
data_out =\
[{'address': u'2a00:2384:0:208f::13',
'hostname': u'static.bt.com',
'ports': [{80: {'reason': u'syn-ack', 'state': u'open'}},
{443: {'reason': u'syn-ack',
'ssl_cert': u'place holder',
'state': u'open'}}]}]
根据@jonrsharpe之前的建议,我创建了一个帮助函数,使我能够找到键。这证明是有帮助的,但我仍然在努力获得理想的结果。
def find_key(data, search_key, out=None):
"""Find all values from a nested dictionary for a given key."""
if out is None:
out = []
if isinstance(data, dict):
if search_key in data:
out.append(data[search_key])
for key in data:
find_key(data[key], search_key, out)
return out
这里真的很感激任何帮助!
答案 0 :(得分:0)
这并不是那么难;你只需要查看导致你想要的数据结构 - 这会因为格式不佳而变得更加困难,所以我重新缩进你的输入并标记了键(<==
)和字段({ {1}})你正在寻找:
!!!
同样适用于您想要的输出(经适当调整):
data_in = {
'map': {
'stats': {
'uphosts': u'3',
'timestr': u'Thu Mar 20 18:18:09 2014',
'downhosts': u'0',
'totalhosts': u'3',
'elapsed': u'1.71'
},
'scaninfo': {
u'tcp': {
'services': u'80,443',
'method': u'syn'
}
},
'command_line': u'command goes here'
},
'scan': { # <==
u'2a00:2384:0:208f::13': { # <== !!!
'status': {
'state': u'up',
'reason': u'nd-response'
},
'hostname': u'static.abc.com', # !!!
'vendor': {
u'00:0C:29:7C:13:D3': u'VMware'
},
'addresses': {
u'mac': u'00:gf:88:9:56:D5',
u'ipv6': u'2a00:2384:0:f467::13'
},
u'tcp': { # <==
80: { # <== !!!
'product': '',
'state': u'open', # !!!
'version': '',
'name': u'http',
'conf': u'3',
'extrainfo': '',
'reason': u'syn-ack', # !!!
'cpe': ''
},
443: { # <== !!!
'product': '',
'state': u'open', # !!!
'version': '',
'name': u'https',
'conf': u'3',
'script': { # <==
u'ssl-cert': u'place holder' # !!!
},
'extrainfo': '',
'reason': u'syn-ack', # !!!
'cpe': ''
}
}
},
u'2a00:2384:0:208f::15': {
'status': {
'state': u'up',
'reason': u'nd-response'
},
'hostname': u'static.xyz.com',
'vendor': {
u'00:0C:67:99:6f:96': u'VMware'
},
'addresses': {
u'mac': u'00:gf:29:99:6D:96',
u'ipv6': u'a848:2384:0:3456::15'
},
u'tcp': {
80: {
'product': '',
'state': u'open',
'version': '',
'name': u'http',
'conf': u'3',
'extrainfo': '',
'reason': u'syn-ack',
'cpe': ''
},
443: {
'product': '',
'state': u'open',
'version': '',
'name': u'https',
'conf': u'3',
'script': {
u'ssl-cert': u'place holder'
},
'extrainfo': '',
'reason': u'syn-ack',
'cpe': ''
}
}
},
u'2a00:2384:0:208f::16': {
'status': {
'state': u'up',
'reason': u'nd-response'
},
'hostname': u'static.edf.com',
'vendor': {
u'00:0C:55:AE:33:ff': u'VMware'
},
'addresses': {
u'mac': u'00:54:29:fg:55:0F',
u'ipv6': u'8938:8584:0:8685::16'
},
u'tcp': {
80: {
'product': '',
'state': u'open',
'version': '',
'name': u'http',
'conf': u'3',
'extrainfo': '',
'reason': u'syn-ack',
'cpe': ''
},
443: {
'product': '',
'state': u'open',
'version': '',
'name': u'https',
'conf': u'3',
'script': {
u'ssl-cert': u'place holder'
},
'extrainfo': '',
'reason': u'syn-ack',
'cpe': ''
}
}
}
}
}
然后提取变为:
data_out = [
{
'address': u'2a00:2384:0:208f::13',
'hostname': u'static.bt.com',
'ports': {
80: {
'state': u'open',
'reason': u'syn-ack'
},
443: {
'ssl_cert': u'place holder',
'state': u'open',
'reason': u'syn-ack'
}
}
}
]
导致所需的输出,
def remap_port(port, port_data):
result = {
"state": port_data["state"],
"reason": port_data["reason"]
}
try:
result["ssl_cert"] = port_data["script"]["ssl-cert"]
except KeyError:
pass
return port, result
def remap_scanned_address(address, address_data):
return {
"address": address,
"hostname": address_data["hostname"],
"ports": dict(remap_port(port, port_data) for port,port_data in address_data["tcp"].items())
}
def remap_scan_data(data_in):
return [remap_scanned_address(address, address_data) for address, address_data in data_in["scan"].items()]
data_out = remap_scan_data(data_in)