2013-10-10 117 views
1

我试图从下面的XML文件中的一些元素(下调nmap输出):解析nmap的XML报告与Python

<?xml version="1.0"?> 
<nmaprun> 
<host starttime="1381245200" endtime="1381245316"> 
    <address addr="192.168.1.5" addrtype="ipv4"/> 
    <hostnames> 
     <hostname name="host1.example.com" type="PTR"/> 
    </hostnames> 
    <os> 
     <osmatch> 
     <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="100"> 
      <cpe>cpe:/o:linux:linux_kernel:2.6</cpe> 
     </osclass> 
     </osmatch> 
    </os> 
    </host> 
</nmaprun> 

用下面的代码:

import xml.etree.ElementTree as ET 

d = [ 
     {'path': 'address', 'el': 'addr'}, 
     {'path': 'hostnames/hostname', 'el': 'name'}, 
     {'path': 'os/osmatch/osclass', 'el': 'osfamily'} 
] 

tree = ET.parse('testnmap.xml') 
root = tree.getroot() 
for i in root.iter('host'): 
     for h in d: 
       if i.find(h['path']): print i.find(h['path']).get(h['el']) 
       else: print "UNKNOWN ", (h['path']) 

的想法是提取IP,主机名和操作系统。输出给我

UNKNOWN address 
UNKNOWN hostnames/hostname 
Linux 

所以最里面的路径工作(osfamily),而其他(主机名)失败。接触他们的正确方法是什么?

+1

作为替代,可以考虑使用包括在分配使用nmap的Ndiff Python脚本解析器。它专门用于解析Nmap XML并在Python对象中返回结果。 – bonsaiviking

回答

1

我认为问题是i.find(h['path'])的布尔比较。它检查该元素是否有子元素,并且只发生在<osclass>。你必须检查它是否为空,比较None,如:

... 
e = i.find(h['path']) 
if e is not None: print(e.get(h['el'])) 
... 

它产生:

192.168.1.5 
host1.example.com 
Linux 
+0

我不知道我明白:调用'i.find(“os/osmatch/osclass”)'和'i.find(“主机名/主机名”)'之间有什么区别,.get()之后达到在这两种情况下,标签内的元素(我的意思是他们从“”)获得“aaa”值。你的代码工作并解决问题 - 这只是我明白为什么它的工作原理:) – WoJ

+0

@Woj:据我所知,当一个元素存在但没有子元素时,它返回'False',并且当元素不存在时返回'无'。在布尔上下文中,两个值都被解释为“False”,因此需要使用“None”进行显式检查来过滤那些无法找到的元素。所以''因为它没有孩子而是'UNKNOWN',但''有一个,''。 – Birei

+0

现在一切都很清楚 - 我没有意识到有两个不同的值根据孩子的存在而返回,两个'if'都是'if'。感谢您的澄清! – WoJ