代码仅将<ports>标签内首个开放端口写入CSV文件的问题咨询
解决Nmap XML解析仅导出首个开放端口的问题
问题重现
执行命令生成扫描结果:
nmap -sV -Pn -oX Output_3.xml scanme.nmap.org
用Python解析该XML文件时,仅能将<ports>标签内的首个开放端口写入detected_hosts.csv,其余开放端口全部丢失。
问题根源
原代码中所有端口相关的取值都用了[0]硬索引,只获取了第一个<port>元素的数据,完全没遍历当前主机下的所有端口,所以只会导出第一个开放端口的信息。
修复后的代码
import xml.etree.ElementTree as ET import csv def main(): in_xml_port = 'Output_3.xml' # 注意和生成的XML文件名保持一致 xml_tree_port = ET.parse(in_xml_port) xml_root_port = xml_tree_port.getroot() # 写入CSV文件 with open('detected_hosts.csv', 'w', newline='', encoding='utf-8') as file: writer = csv.writer(file) writer.writerow(['IP', 'Hostname', 'Status', 'Port', 'Service', 'Protocol', 'Product']) for host in xml_root_port.findall('host'): # 获取IP地址 master_ip = host.find('address').get('addr') # 处理主机名:无主机名时用N/A替代 master_hostname = 'N/A' hostnames_node = host.find('hostnames') if hostnames_node: hostname_node = hostnames_node.find('hostname') if hostname_node: master_hostname = hostname_node.attrib['name'] # 跳过无端口信息的主机 ports_node = host.find('ports') if not ports_node: continue # 遍历当前主机的所有端口 for port in ports_node.findall('port'): # 获取端口状态 state_node = port.find('state') port_state = state_node.attrib['state'] if state_node else 'unknown' # 只处理开放端口 if port_state != 'open': continue # 获取端口号和协议 port_id = port.attrib['portid'] port_protocol = port.attrib['protocol'] # 处理服务信息:无服务时用默认值 service_node = port.find('service') service_name = service_node.attrib['name'] if service_node else 'unknown' product_name = service_node.attrib.get('product', 'N/A') if service_node else 'N/A' # 写入CSV行 writer.writerow([master_ip, master_hostname, port_state, port_id, service_name, port_protocol, product_name]) if __name__ == '__main__': main()
关键修改点
- 遍历所有端口:移除原代码中
[0]的硬索引,改为遍历当前主机下的每个<port>元素,确保所有开放端口都被处理 - 边界情况处理:增加了对无主机名、无端口信息、无服务信息的判断,避免因XML节点缺失导致的索引错误
- 简化逻辑:用
find替代findall[0],代码更简洁且更安全 - 精准过滤:只在端口状态为
open时写入数据,减少无效条目
内容的提问来源于stack exchange,提问作者Nitheesh Paul
相关产品推荐
相关产品推荐

