我使用Python解析nessus扫描的iterparse结果(.nessus文件)。对于意外的记录,解析失败,尽管类似的记录已被正确解析。
XML文件的一般结构由许多如下所示的记录组成:
<ReportHost>
<ReportItem>
<foo>9.3</foo>
<bar>hello</bar>
</ReportItem>
<ReportItem>
<foo>10.0</foo>
<bar>world</bar>
</ReportHost>
<ReportHost>
...
</ReportHost>换句话说,很多主机(ReportHost)有很多项要报告(ReportItem),而后者有几个特征(foo,bar)。我将考虑为每个项目生成一行,以及它的特征。
在文件中间的简单一行(本例中为cvss_base_score)处解析失败
<cvss_base_score>9.3</cvss_base_score>而大约200行类似的代码行已经被解析,没有出现问题。
相关的代码片段如下--它设置上下文标记(inReportHost和inReportEvent,它们告诉我我在XML文件的结构中的什么位置,并根据上下文赋值或打印值)
import xml.etree.cElementTree as ET
inReportHost = False
inReportItem = False
for event, elem in ET.iterparse("test2.nessus", events=("start", "end")):
if event == 'start' and elem.tag == "ReportHost":
inReportHost = True
if event == 'end' and elem.tag == "ReportHost":
inReportHost = False
elem.clear()
if inReportHost:
if event == 'start' and elem.tag == 'ReportItem':
inReportItem = True
cvss = ''
if event == 'start' and inReportItem:
if event == 'start' and elem.tag == 'cvss_base_score':
cvss = elem.text
if event == 'end' and elem.tag == 'ReportItem':
print cvss
inReportItem = Falsecvss有时会有None值(在cvss = elem.text赋值之后),即使相同的条目在文件中之前已被正确解析。
如果我在赋值下面添加一些类似如下的内容
if cvss is None: cvss = "0"然后,解析更多的cvss时会分配适当的值(有些则为空)。
当使用导致错误解析的<ReportHost>...</reportHost>并在程序中运行它时-它工作得很好(即。正如预期的那样,cvss被分配了9.3 )。
我在代码中的错误之处迷失了方向,因为有一大组相似的记录,有些是正确处理的,有些是不正确的(有些记录是相同的,但处理方式仍然是不同的)。我也找不到任何关于失败的记录的特别之处--早些时候和晚些时候完全相同的记录都可以。
发布于 2013-02-03 18:23:58
注意: iterparse()只保证它在发出“start”事件时看到了开始标记的“>”字符,所以属性是定义的,但文本和尾属性的内容在这一点上是未定义的。这同样适用于元素的子元素;它们可能存在,也可能不存在。如果您需要一个完全填充的元素,请改为查找“end”事件。
删除inReport*变量,并在完全解析"end“事件时仅处理ReportHost。使用ElementTree接口从当前的ReportHost元素中获取必要的信息,如cvss_base_score。
要保留内存,请执行以下操作:
import xml.etree.cElementTree as etree
def getelements(filename_or_file, tag):
context = iter(etree.iterparse(filename_or_file, events=('start', 'end')))
_, root = next(context) # get root element
for event, elem in context:
if event == 'end' and elem.tag == tag:
yield elem
root.clear() # preserve memory
for host in getelements("test2.nessus", "ReportHost"):
for cvss_el in host.iter("cvss_base_score"):
print(cvss_el.text)https://stackoverflow.com/questions/14670792
复制相似问题