Python解析OWASP ZAP XML报告并导出Excel的最优方案咨询
问题解决:OWASP ZAP XML解析优化与Excel导出实现
一、XML解析代码评估与优化
当前代码的问题
- 临时数据存储风险:用实例变量
self.site_name等存储单条站点信息,多文件/多站点循环时,若某轮未找到site节点,会残留上一轮数据。 - XPath路径冗余:
site.findall('.//alertitem')会遍历整个XML文档查找节点,应该使用更精确的路径限制在当前site节点下,提升效率。 - 数据结构可读性差:用列表存储站点和漏洞信息,后续处理字段时易出错,且难以维护。
- 缺少异常处理:若XML中某个标签缺失(比如
instances为空),alert.find('instances').text会直接抛出AttributeError。 - 文件遍历不严谨:
os.listdir会返回目录,未做文件类型二次判断,可能导致解析出错。
优化后的代码
使用dataclasses定义结构化数据,结合glob筛选文件,添加异常处理,采用精确XPath:
from dataclasses import dataclass import glob import os import xml.etree.ElementTree as Et @dataclass class Site: name: str host: str port: str ssl: str @dataclass class Alert: site_host: str site_port: str site_ssl: str name: str risk_code: str confidence: str risk_desc: str confidence_desc: str desc: str instances: str ref: str class ZAPReportParser: def __init__(self, zap_folder): self.path_zap = zap_folder self.sites: list[Site] = [] self.alerts: list[Alert] = [] def process_xml_folder(self): # 用glob直接筛选XML文件,替代手动判断 for xml_path in glob.glob(os.path.join(self.path_zap, "*.xml")): tree = Et.parse(xml_path) root = tree.getroot() for site in root.findall('.//site'): # 用局部变量存储当前站点数据,避免实例变量污染 site_name = site.get('name', '') site_host = site.get('host', '') site_port = site.get('port', '') site_ssl = site.get('ssl', '') self.sites.append(Site(site_name, site_host, site_port, site_ssl)) # 精确查找当前site下的alertitem节点(匹配ZAP XML结构) for alert in site.findall('./alerts/alertitem'): # 用findtext方法,标签不存在时返回默认空字符串,避免报错 alert_ref = alert.findtext('alertRef', '') alert_name = alert.findtext('alert', '') alert_risk_code = alert.findtext('riskcode', '') alert_confidence = alert.findtext('confidence', '') alert_risk_desc = alert.findtext('riskdesc', '') alert_confidence_desc = alert.findtext('confidencedesc', '') alert_desc = alert.findtext('desc', '') alert_instances = alert.findtext('instances', '') self.alerts.append(Alert( site_host=site_host, site_port=site_port, site_ssl=site_ssl, name=alert_name, risk_code=alert_risk_code, confidence=alert_confidence, risk_desc=alert_risk_desc, confidence_desc=alert_confidence_desc, desc=alert_desc, instances=alert_instances, ref=alert_ref ))
二、xlsxwriter导出Excel格式实现
要实现每个漏洞包含全量信息的表格,只需将结构化的Alert数据逐行写入Excel,还可添加格式优化(比如高风险项高亮):
import xlsxwriter def export_alerts_to_excel(alerts: list[Alert], output_path): workbook = xlsxwriter.Workbook(output_path) worksheet = workbook.add_worksheet("ZAP漏洞报告") # 定义表头 headers = [ "主机", "端口", "是否SSL", "漏洞名称", "风险代码", "可信度", "风险描述", "可信度描述", "漏洞详情", "实例", "漏洞参考" ] # 定义格式:表头加粗灰色填充,高风险项红色填充 header_format = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter', 'bg_color': '#D3D3D3'}) high_risk_format = workbook.add_format({'bg_color': '#FFC7CE'}) # 写入表头 for col, header in enumerate(headers): worksheet.write(0, col, header, header_format) # 设置列宽,避免内容被截断 worksheet.set_column(0, 0, 15) worksheet.set_column(1, 1, 8) worksheet.set_column(2, 2, 10) worksheet.set_column(3, 3, 30) worksheet.set_column(4, 4, 10) worksheet.set_column(5, 5, 10) worksheet.set_column(6, 6, 20) worksheet.set_column(7, 7, 20) worksheet.set_column(8, 8, 50) worksheet.set_column(9, 9, 50) worksheet.set_column(10, 10, 15) # 写入漏洞数据 for row, alert in enumerate(alerts, start=1): row_data = [ alert.site_host, alert.site_port, alert.site_ssl, alert.name, alert.risk_code, alert.confidence, alert.risk_desc, alert.confidence_desc, alert.desc, alert.instances, alert.ref ] for col, value in enumerate(row_data): # 风险代码为3(高风险)时应用红色格式 cell_format = high_risk_format if col == 4 and value == '3' else None worksheet.write(row, col, value, cell_format) workbook.close()
使用示例
if __name__ == "__main__": parser = ZAPReportParser("/path/to/zap/xml/reports") parser.process_xml_folder() export_alerts_to_excel(parser.alerts, "zap_vulnerabilities.xlsx")
内容的提问来源于stack exchange,提问作者Francesco Andronico
相关产品推荐
相关产品推荐

