迭代Python数据结构

迭代Python数据结构,python,Python,我很难理解这个Python数据结构: data = {'nmap': {'command_line': u'ls', 'scaninfo': {u'tcp': {'method': u'connect', 'services': u'80,443'}}, 'scanstats': {'downhosts': u'0',

我很难理解这个Python数据结构:

 data = {'nmap': {'command_line': u'ls',
                  'scaninfo': {u'tcp': {'method': u'connect',
                                        'services': u'80,443'}},
                  'scanstats': {'downhosts': u'0',
                                'elapsed': u'1.18',
                                'timestr': u'Wed Mar 19 21:37:54 2014',
                                'totalhosts': u'1',
                                'uphosts': u'1'}},
         'scan': {u'url': {'addresses': {u'ipv6': u'2001:470:0:63::2'},
                                        'hostname': u'abc.net',
                                        'status': {'reason': u'syn-ack',
                                                   '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': {}
         }
         }
 }
基本上,我需要迭代“tcp”键值,并提取“script”项(如果存在)的内容

这就是我尝试过的:

items = data["scan"]
for item in items['url']['tcp']:
    if t["script"] is not None:
        print t  

然而,我似乎无法让它工作。

你是说
如果项目[“脚本”]

实际上,如果密钥可能不存在,请使用
dict
提供的
get
方法

所以试着去做吧

items = data["scan"]
for item in items['url']['tcp']:
    script = item.get('script')
    if script:
        print script

data['scan']['url']['tcp']
是一个字典,因此当您在它上面进行迭代时,您将得到键,而不是值。如果要迭代这些值,必须执行以下操作:

for t in data['scan']['url']['tcp'].values():
    if 'script' in t and t['script'] is not None:
        print(t)
如果您还需要密钥,请迭代这些项:

for k, t in data['scan']['url']['tcp'].items():
    if 'script' in t and t['script'] is not None:
        print(k, t)

您还需要先更改测试以检查t中的
'script',否则访问
t['script']
将引发一个键错误。

这将在数据结构中的任何位置找到任何带有键
'script'
的字典项:

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
对于您的数据,我得到:

>>> find_key(data, 'script')
[{'ssl-cert': 'place holder'}]

要查找端口,请稍微修改:

tcp_dicts = find_key(data, 'tcp') # find all values for key 'tcp'
ports = [] # list to hold ports
for d in tcp_dicts: # iterate through values for key 'tcp'
    if all(isinstance(port, int) for port in d): # ensure all are port numbers
        for port in d:
            ports.append((port, 
                          d[port].get('script'))) # extract number and script
现在你可以得到如下结果:

[(80, None), (443, {'ssl-cert': 'place holder'})]

你把
项目
t
搞错了。顺便说一句,太好了!谢谢你的帮助。这里还有一个问题。如果我想在out数据中包含“tcp”端口,即80和443,我该怎么做?不确定我是否同意你的观点!我假设我保持原来的函数不变?我好像没法让它工作!基本上,我在输出数据中需要的位是:“ipv6”地址、“主机名”、“tcp”端口号、“状态”和“脚本”的内容。啊,我看到有些地方键
“tcp”
没有提供端口号字典。我已更新以处理此问题。是的,这是使用
find\u key
的现有实现。所有这些问题都不在你的问题中,你仍然可以使用
find\u key
来解决。太好了!知道了。再次感谢,非常感谢。