iterparse无法解析字段,而其他类似的字段则是fin

2024-05-21 11:53:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用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),后者有几个特征(foobar)。我将考虑为每个项目生成一行,以及它的特性。在

解析在文件中间的一行中失败(foo,在这种情况下是cvss_base_score

^{pr2}$

而大约200条类似的行已经被解析,没有问题。在

相关的代码如下——它设置了上下文标记(inReportHost和{}),它们告诉我在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)。在

我不知道我在代码中犯了一个错误,因为在大量类似的记录中,有些记录被正确地处理了,有些记录没有被正确地处理(有些记录是相同的,但处理方式仍然不同)。我也找不到任何关于失败的记录的特别之处——之前和之后相同的记录都可以。在


Tags: and文件eventfalseiffootag记录
1条回答
网友
1楼 · 发布于 2024-05-21 11:53:01

iterparse() docs

Note: iterparse() only guarantees that it has seen the “>” character of a starting tag when it emits a “start” event, so the attributes are defined, but the contents of the text and tail attributes are undefined at that point. The same applies to the element children; they may or may not be present. If you need a fully populated element, look for “end” events instead.

仅在“end”事件完全解析时删除inReport*变量并处理ReportHost。使用elementtreeapi从当前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)

相关问题 更多 >