2015-10-20 57 views
0

我想解析NMAP XML文件中的特定值。 xml文件的部分看起来像这样:Python解析NMAP XML输出“elem key =”NodeList

<nmaprun scanner="nmap" args="nmap -A -P0 -oA scanoutput 192.168.1.5" start="1445258532" startstr="Mon Oct 19 08:42:12 2015" version="6.47" xmloutputversion="1.04"> 
    <hostscript> 
     <script id="smb-os-discovery" output="&#10; OS: Windows Server 2008 R2 Standard 7601 Service Pack 1 (Windows Server 2008 R2 Standard 6.1)&#10; OS CPE: cpe:/o:microsoft:windows_server_2008::sp1&#10; Computer name: SOMEHOSTNAME&#10; NetBIOS computer name: SOMEHOSTNAME&#10; Domain name: domain.local&#10; Forest name: domain.local&#10; FQDN: SOMEHOSTNAME.domain.local&#10; System time: 2015-10-19T08:50:07-04:00&#10;"> 
      <elem key="os">Windows Server 2008 R2 Standard 7601 Service Pack 1</elem> 
      <elem key="lanmanager">Windows Server 2008 R2 Standard 6.1</elem> 
      <elem key="server">SOMEHOSTNAME\x00</elem> 
      <elem key="date">2015-10-19T08:50:07-04:00</elem> 
      <elem key="fqdn">SOMEHOSTNAME.domain.local</elem> 
      <elem key="domain_dns">domain.local</elem> 
      <elem key="forest_dns">domain.local</elem> 
      <elem key="workgroup">HOME\x00</elem> 
      <elem key="cpe">cpe:/o:microsoft:windows_server_2008::sp1</elem> 
     </script> 
    </hostscript> 
</nmaprun> 

我想从每个键的值,但不知道如何解决它。例如,如何从得到的值elem key =“os”?到目前为止,我可以得到完整的输出,但是当我将它添加到CSV中时,它会变得杂乱,我需要分别将每个值分开。下面是我的代码有:

serveros = [script.getAttribute('output') for script in hosttag.getElementsByTagName('script') if script.getAttribute('id') == 'smb-os-discovery'] 

如果我将其更改为:

serveros = [script.getElementsByTagName('os') for script in hosttag.getElementsByTagName('script') if script.getAttribute('id') == 'smb-os-discovery'] 

我得到这个错误:

TypeError: sequence item 0: expected string, NodeList found 

提前感谢!

+0

是否使用[LXML(http://lxml.de/)模块?如果是这样,它允许XPath:'// elem [key ='os']' – Parfait

+0

使用xml.dom.minidom – user1781482

+0

那么考虑,lxml作为[minidom](http://stackoverflow.com/questions/12815637/python- minidom-xml-query)受节点和属性查询XML的限制。 – Parfait

回答

0

也许是这样的:

class ScriptResult: 
    def __init__(self, script, port_number): 
     self.port_number = port_number 
     for k,v in script.attrib.iteritems(): 
      self.__dict__[k] = v 
     return 

    def __str__(self): 
     d = '\n' 
     for k,v in self.__dict__.iteritems(): 
      d += ' %-30s : %s\n' % (k,v) 
     return "ScriptResult(%s)\n" % d 

class Host: 
    def __init__(self): 
     self.script_results = [] # define list of script results 
     return 

    def print_results(self): 
     for i in self.script_results: 
      print i 
     return 


class XML_Parser: 

    def get_hostscripts(self, host, xml_host_element): 
     for hs in xml_host_element.findall('hostscript'): 
      for s in hs.findall('script'): 
       host.script_results.append(ScriptResult(s, 'host')) 
+0

你应该解释这是如何工作的。 – Laurel

+0

好的...原始海报试图读取Nmap XML文件。这些文件很混乱。脚本用任何他们认为重要的信息填充XML。原始海报试图使用DOM findall工具在XML级别处理此问题。我所提供的例子不是在XML层面上工作,而是将所有XML都放到一个类对象中。然后在Python的高层次上,你可以根据需要获取并设置它们的格式。特别是如果您使用可以容忍缺失值并提供默认值的getattr方法。 – sls

+0

'self.analyze_script_smb_os_discovery(项目,S,SCRIPT_NAME,script_output) 高清analyze_script_smb_os_discovery(个体经营,项目,S,SCRIPT_NAME,script_output): 如果SCRIPT_NAME = 'SMB-OS-发现': 回报 script_output = script_output.strip ()[i] [0] .strip(),i [2] .strip()() odist = [i.partition(':')for script_output.split('\ n')] ))为我在olist])' – sls