如何遍历使用Python的elementtree模块解析的元素树?
我昨天花了大约半天时间在交互式的Python命令行上玩ElementTree,结果搞得我一头雾水。根据这个网站 https://docs.python.org/2/library/xml.etree.elementtree.html#module-xml.etree.ElementTree,我通过以下方式加载了树:
import xml.etree.ElementTree as ET
tree = ET.parse('nmaptest.xml')
root = tree.getroot()
然后我开始看一些例子,试着弄明白如何访问和遍历每个元素。每当我觉得自己开始理解它是怎么构成的时候,结果又无法实现我想要的功能。
最终我想解析这些数据,并把相关信息放进数据库,以便以后比较(或者也许写个脚本来简单比较两个XML文档,但目前这超出了我的能力范围)。
我尝试了一些像下面这样的代码:
for host in root.iter('host'):
print host.attrib['name']
for address in host.iter('address'):
print address.attrib['addr']
for port in host.iter('port'):
print port.attrib['portid']
我想打印出每个主机名、IP地址和开放的端口……但是效果不太好,感觉主机名和地址就像在完全不同的世界里,我也不知道为什么会这样。我还发现可以通过简单地这样做来访问地址:
print host[1].attrib['addr']
但我发现当用整数索引时,比如上面的情况(因为host[3]似乎并不是主机名,虽然从逻辑上讲应该是,而host[2]看起来是主机名,但没有.attrib或其他东西),我找不到任何一致性。有时候我觉得找到了我想要的东西,但看到的却是像这样:
for host in root.iter('host'):
print host[1].attrib
{'addrtype': 'ipv4', 'addr': '10.1.102.255'}
我在某些东西上调用.attrib时,看到的却是空的括号{},就像我这样做时:
for host in root.iter('host'):
print host[2].attrib
所以我完全不明白它是如何解析这个文档的……我想知道有没有人能帮我理清思路,或者指引我一些可能有帮助的文档?
这是XML输出中的一个示例条目……
<host starttime="1408488852" endtime="1408499159"><status state="up" reason="user-set" reason_ttl="0"/>
<address addr="X.X.X.X" addrtype="ipv4"/>
<hostnames>
<hostname name="computername.domainname.com" type="PTR"/>
</hostnames>
<ports>
<extraports state="filtered" count="986">
<extrareasons reason="no-responses" count="986"/>
</extraports>
<port protocol="tcp" portid="X"><state state="open" reason="syn-ack" reason_ttl="127"/> <service name="X" method="table" conf="3"/></port>
<port protocol="tcp" portid="X"><state state="open" reason="syn-ack" reason_ttl="127"/> <service name="X" method="table" conf="3"/></port>
<port protocol="tcp" portid="X"><state state="open" reason="syn-ack" reason_ttl="127"/> <service name="X" method="table" conf="3"/></port>
</ports>
<times srtt="332" rttvar="164" to="100000"/>
</host>
1 个回答
1
这段代码中,
for host in root.iter('host'):
print host.attrib['name']
你试图访问host
元素的name
属性。但实际上,hostname
元素才有这个属性。
这里有一种方法可以获取你想提取的数据(假设在nmaptest.xml文件中,有一个或多个host
元素作为共同根元素的子元素):
import xml.etree.ElementTree as ET
tree = ET.parse('nmaptest.xml')
hosts = tree.findall(".//host")
for host in hosts:
for elem in host.iter():
if elem.tag == "hostname":
print elem.attrib['name']
if elem.tag == "address":
print elem.attrib['addr']
if elem.tag == "port":
print elem.attrib['portid']
输出结果:
X.X.X.X
computername.domainname.com
X
X
X