iterparse 无法解析某个字段,而其他类似的则可以

2023-12-06

我用Python的iterparse解析 nessus 扫描的 XML 结果(.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)。我将考虑为每个项目生成一行及其特征。

解析在文件中间的简单行处失败(foo在这种情况下是cvss_base_score)

<cvss_base_score>9.3</cvss_base_score>

同时解析了约 200 条相似的行,没有出现任何问题。

相关的代码如下——它设置上下文标记(inReportHost and 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 = False

cvss有时具有 None 值(在cvss = elem.text分配),即使相同的条目已在文件中的较早位置正确解析。

如果我在作业下面添加一些类似于

if cvss is None: cvss = "0"

然后进一步解析许多cvss分配它们适当的值(还有一些是 None )。

当采取<ReportHost>...</reportHost>这会导致错误的解析并通过程序运行它 - 它工作正常(即cvss被安排了9.3正如预期的那样)。

我迷失在我的代码中犯错误的地方,因为对于大量相似的记录,有些记录正确处理,有些记录不正确(有些记录是相同的,但处理方式仍然不同)。我也找不到有关失败记录的任何具体信息 - 之前和之后相同的记录都可以。


来自iterparse() 文档:

注意:iterparse() 只保证它已经看到“>”字符 当它发出“start”事件时,它是一个起始标签,所以属性是 已定义,但 text 和 tail 属性的内容是 那时未定义。这同样适用于元素子元素; 他们可能在场,也可能不在场。如果您需要一个完全填充的元素, 相反,寻找“结束”事件。

Drop inReport*仅在完全解析后的“结束”事件上变量和处理 ReportHost。使用 ElementTree API 获取必要的信息,例如cvss_base_score来自当前 ReportHost 元素。

为了保留记忆,请执行以下操作:

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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iterparse 无法解析某个字段,而其他类似的则可以 的相关文章

随机推荐