考虑一下你是否会拥有默认的nmap XML输出。
我特意试图解析IP地址(这里没问题)和OS供应商(这是问题)。
问题是因为xml标记有几个实例,以及属性,我无法弄清楚如何使用untangle语法从也需要索引的标记中提取和归属。
xml看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?>
<!-- Nmap 7.40 scan initiated Tue Aug 29 12:45:56 2017 as: nmap -sV -O -oX ./nmap_results.xml 1.2.3.4/24 -->
<nmaprun attributes="">
<scaninfo attributes="" />
<debugging attributes="" />
<host attributes="">
<status attributes="" />
<address attributes="" />
<hostnames>
<hostname attributes="" />
</hostnames>
<ports>
<extraports attributes="">
<extrareasons attributes="" />
</extraports>
<port attributes="">
<state attributes="" />
<service attributes="" />
</port>
<port attributes="">
<state attributes="" />
<service attributes="">
<cpe>stuff</cpe>
<cpe>more stuff</cpe>
</service>
</port>
...
让我们假设我想从第一个端口实例中提取属性。
在我的python中,我认为它看起来像这样:
#!/bin/env python
import untangle
nmap = untangle.parse('./location/to/results.xml')
alive = int(nmap.nmaprun.runstats.hosts['up'])
count = range(0,alive,1)
for tick in count:
print(nmap.nmaprun.host[tick].ports.port[0, 'attribute'])
这里的问题是端口[0,&#39;属性&#39;]的实例,因为它想要并且需要0索引,但是还有我想要提取的属性。
这是python错误:
/usr/bin/python2.7 /path/to/my/dot.py
Traceback (most recent call last):
File "/path/to/my/dot.py", line 10, in <module>
print(nmap.nmaprun.host[tick].ports.port[0, 'vendor'])
TypeError: list indices must be integers, not tuple
Process finished with exit code 1
如果我尝试仅使用属性名称而没有索引,我会得到:
/usr/bin/python2.7 /path/to/my/dot.py
Traceback (most recent call last):
File "/path/to/my/dot.py", line 10, in <module>
print(nmap.nmaprun.host[tick].ports.port['vendor'])
TypeError: list indices must be integers, not str
Process finished with exit code 1
如果我只提供索引,我会得到一个包含所有属性的字符串,但我只需要一个。
我做错了什么或有办法吗?
答案 0 :(得分:0)
我没有盲目猜测,而是下载了模块(它是一个 .py 文件)并开始使用它。我学到了什么:
untangle.Element
)的树状结构标签(将成为对象属性)Element
支持索引([Python]: object.__getitem__(self, key))并返回名称与给定密钥匹配的 xml 节点属性Element
个对象的列表 Element
支持迭代([Python]: object.__iter__(self))并在迭代时产生自身从子弹3.和4.结果它&#39;最好总是遍历一个元素,该元素可以出现一次或多次 旁注* 。
这里有一些代码可以证明:
#!/bin/env python
import untangle
FILE_NAME = "a.xml" # "./location/to/results.xml" # You should change the name back to match your location
def main():
nmap = untangle.parse(FILE_NAME)
up_host_count = int(nmap.nmaprun.runstats.hosts['up'])
host_iterator = nmap.nmaprun.host
for host in host_iterator:
print("IP Address: {}".format(host.address["addr"]))
vendors = set()
osmatch_iterator = host.os.osmatch
for osmatch in osmatch_iterator:
osclass_iterator = osmatch.osclass
for osclass in osclass_iterator:
vendor = osclass["vendor"]
if vendor is not None:
vendors.add(vendor)
print(" OS Vendors: {}".format(vendors))
port_iterator = host.ports.port
for port in port_iterator:
print(" Port number: {}".format(port["portid"]))
if __name__ == "__main__":
main()
备注强>:
for
循环都是迭代的一个例子(我在上面讨论过),我从提供的 xml 示例(完整版本)中得到它,看看它在哪里有多个节点具有相同的标签osclass
节点指定 Linux 以外的供应商并看到它出现在输出中)<强>输出强>:
E:\Work\Dev\StackOverflow\q45946779>python b.py IP Address: 127.0.0.1 OS Vendors: set([u'Linux']) Port number: 22 Port number: 111 Port number: 631 Port number: 2222 Port number: 8081 Port number: 30000
旁注* :我谈过一个可能出现一次或多次的元素,但这种方法(我在谈论untangle
模块方法)并不是很错误验证 xml 是否不完整。采取以下代码行(不再使用,但我保留它只是为了说明一点):
up_host_count = int(nmap.nmaprun.runstats.hosts['up'])
如果 xml 中缺少任何节点nmaprun
,runstats
,hosts
,该行将吐出 AttributeError 。相同的行,但具有防错功能,如下所示:
up_host_count = int(getattr(getattr(getattr(nmap, "nmaprun", None), "runstats", None), "hosts", None)["up"] or 0)
但这很难看,而且在推进 xml 树深度时会变得更加混乱。