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
  •  | 
  •  

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?

有帮助吗?

解决方案

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.

其他提示

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']
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top