How to get the IP address from a nmap output in XML with an specific vendor using ElementTree in Python

StackOverflow https://stackoverflow.com/questions/22311156

  •  12-06-2023
  •  | 
  •  

Question

Using the XML output from nmap for the reachable virtual machines running on the host machine - obtained with nmap -oX output.xml -sP 192.168.2.*, I'd like to get the IP address of each machine whose vendor matches QEMU Virtual NIC. I chose to use Python's ElementTree XML API to do that, but I'm having trouble isolating the host elements with the specified address elements.

Here it goes a snippet of the XML output to be used:

<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.93" addrtype="ipv4"/>
<address addr="52:54:00:E2:17:31" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="1023" rttvar="5000" to="100000"/>
</host>
<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.96" addrtype="ipv4"/>
<address addr="52:54:00:45:86:8A" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="155" rttvar="5000" to="100000"/>
</host>
<host><status state="up" reason="arp-response"/>
<address addr="192.168.2.103" addrtype="ipv4"/>
<address addr="52:54:00:61:7A:E5" addrtype="mac" vendor="QEMU Virtual NIC"/>
<hostnames>
</hostnames>
<times srtt="391" rttvar="5000" to="100000"/>
</host>

Using findall and the XPath syntax below, I could find the address elements which have the wanted vendor attribute:

import xml.etree.ElementTree as ET
tree = ET.parse('output.xml')
tree.findall("./host/address/[@vendor='QEMU Virtual NIC']")

But what I really want are the host elements which own the address elements found above, so I can then find the other address sub-elements of type "ipv4" for the same host so I can finally have the host IP address. Can anyone point me in the right direction to achieve that using XPath and ElementTree?

Était-ce utile?

La solution

If you must use ElementTree (and not lxml)

>>> [i.get('addr') for i in tree.findall(
...     './host/address[@vendor="QEMU Virtual NIC"]/../address[@addrtype="ipv4"]')]
['192.168.2.93', '192.168.2.96', '192.168.2.103']

lxml is a much better library but if external dependencies are not allowed this will have to do.

Autres conseils

The hosts:

./host[address[@vendor="QEMU Virtual NIC"]]

The IPv4 addresses:

./host[address[@vendor="QEMU Virtual NIC"]]/address[@addrtype="ipv4"]/@addr

Interactively using lxml:

>>> from lxml import etree
>>> doc = etree.XML("""<doc><host><status state="up" reason="arp-response"/>
... <address addr="192.168.2.93" addrtype="ipv4"/>
... <address addr="52:54:00:E2:17:31" addrtype="mac" vendor="QEMU Virtual NIC"/>
... <hostnames>
... </hostnames>
... <times srtt="1023" rttvar="5000" to="100000"/>
... </host>
... <host><status state="up" reason="arp-response"/>
... <address addr="192.168.2.96" addrtype="ipv4"/>
... <address addr="52:54:00:45:86:8A" addrtype="mac" vendor="QEMU Virtual NIC"/>
... <hostnames>
... </hostnames>
... <times srtt="155" rttvar="5000" to="100000"/>
... </host>
... <host><status state="up" reason="arp-response"/>
... <address addr="192.168.2.103" addrtype="ipv4"/>
... <address addr="52:54:00:61:7A:E5" addrtype="mac" vendor="QEMU Virtual NIC"/>
... <hostnames>
... </hostnames>
... <times srtt="391" rttvar="5000" to="100000"/>
... </host></doc>""")
>>> doc.xpath('./host[address[@vendor="QEMU Virtual NIC"]]')
[<Element host at 0xb72c0af4>, <Element host at 0xb72c0b1c>, <Element host at 0xb72c0b44>]
>>> doc.xpath('./host[address[@vendor="QEMU Virtual NIC"]]/address[@addrtype="ipv4"]/@addr')
['192.168.2.93', '192.168.2.96', '192.168.2.103']
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top