Ruby哈希取值技巧:解析Nmap扫描JSON动态数据结构问题
解决Nmap JSON输出结构多变的解析痛点
我太懂这种闹心的情况了——Nmap扫出来的JSON真的没那么规整,同一个字段一会儿是单个值、一会儿又变成数组,还有各种组合变体,解析的时候经常卡壳!分享几个我常用的解决思路,亲测好用:
核心思路:统一单个值与数组的处理逻辑
不管输入是单个元素还是数组,我们先把它转成数组格式,这样后续遍历、提取数据的逻辑就不用反复判断类型了。
1. 写一个通用的「转数组」工具函数
比如用Python的话,我会写这么个小函数:
def ensure_list(item): if isinstance(item, list): return item elif item is None: return [] else: return [item]
这个函数的作用很简单:
- 如果输入已经是列表,直接返回
- 如果是
None(字段不存在的情况),返回空列表 - 其他情况(单个字符串、字典等),把它包装成单元素列表
2. 针对Nmap常见可变字段做适配
拿你提到的IP、MAC地址举例,Nmap里的address字段可能是单个地址对象,也可能是多个地址的数组,用工具函数处理后就省心多了:
import json # 加载Nmap的JSON输出 with open('nmap_scan.json', 'r') as f: nmap_data = json.load(f) # 遍历每个主机 for host in ensure_list(nmap_data.get('host')): host_dict = {} # 处理地址(IP/MAC) addresses = ensure_list(host.get('address')) for addr in addresses: addr_type = addr.get('addrtype') if addr_type == 'ipv4' or addr_type == 'ipv6': host_dict['ip'] = addr.get('addr') elif addr_type == 'mac': host_dict['mac'] = addr.get('addr') # 处理其他可能可变的字段,比如主机名 hostnames = ensure_list(host.get('hostnames', {}).get('hostname')) if hostnames: host_dict['hostname'] = hostnames[0].get('name') # 取第一个主机名 # 把整理好的字典存入结果列表 print(host_dict)
3. 容错处理避免报错
Nmap的JSON里有些字段可能不存在,所以尽量用dict.get(key, 默认值)而不是直接用dict[key],这样即使某个字段缺失,也不会抛出KeyError,而是返回None,再通过ensure_list转成空列表,保证逻辑不中断。
4. 嵌套结构同理处理
比如osmatch(操作系统匹配结果)、port(端口信息)这些字段,也可能出现单个/数组的变化,同样套上ensure_list就行:
# 处理操作系统匹配结果 os_matches = ensure_list(host.get('os', {}).get('osmatch')) if os_matches: host_dict['os_guess'] = os_matches[0].get('name') host_dict['os_accuracy'] = os_matches[0].get('accuracy')
总结
其实本质就是先把所有可能的「单个值/数组」统一成数组,再用一套逻辑处理,这样不管Nmap输出是哪种变体,你的解析代码都能稳定运行,不用再为各种情况写一堆判断啦!
内容的提问来源于stack exchange,提问作者Godzilla74
相关产品推荐
相关产品推荐

