Xml-Parsen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
pythonist
User
Beiträge: 40
Registriert: Sonntag 14. Mai 2006, 17:28

Sonntag 14. Mai 2006, 19:53

Also das ist mein erster Post im Forum, also wenn ich was falsch gemacht hab nicht böse sein.
Ich bin gerade dabei Python zu lernen, da wollte ich ein Script schreiben das die Ausgaben von nmap auswerted. Da nmap XML-Ausgabe unterstüzt dachte ich mir, es ist am einfachsten die XML-Datei zu parsen. Allerdings hab ich auch nach durchlesen verschiedener Threats hier im Forum und der Python Library Reference das Parsen von XML-Dateien immernoch nicht versanden. Wär echt Klasse wenn mir das jemand erklären könnte. So sieht die XML aus:

Code: Alles auswählen

<?xml version="1.0" ?>
<?xml-stylesheet href="/usr/share/nmap/nmap.xsl" type="text/xsl"?>
<!-- Nmap 4.01 scan initiated Thu May 11 14:27:55 2006 as: nmap -sS -oX /tmp/nmap.xml -p 21 192.168.0.1-50 -->
<nmaprun scanner="nmap" args="nmap -sS -oX /tmp/nmap.xml -p 21 192.168.0.1-50" start="1147350475" startstr="Thu May 11 14:27:55 2006" version="4.01" xmloutputversion="1.01">
<scaninfo type="syn" protocol="tcp" numservices="1" services="21" />
<verbose level="0" />
<debugging level="0" />
<host><status state="up" />
<address addr="192.168.0.1" addrtype="ipv4" />
<address addr="xxxx" addrtype="mac" vendor="AVM GmbH" />
<hostnames><hostname name="fritz.fonwlan.box" type="PTR" /></hostnames>
<ports><extraports state="unknown" count="0" />
<port protocol="tcp" portid="21"><state state="closed" /><service name="ftp" method="table" conf="3" /></port>
</ports>
</host>
<host><status state="up" />
<address addr="192.168.0.22" addrtype="ipv4" />
<address addr="xxxx" addrtype="mac" vendor="Micro-star International CO." />
<hostnames><hostname name="host1" type="PTR" /></hostnames>
<ports><extraports state="unknown" count="0" />
<port protocol="tcp" portid="21"><state state="filtered" /><service name="ftp" method="table" conf="3" /></port>
</ports>
</host>
<host><status state="up" />
<address addr="192.168.0.28" addrtype="ipv4" />
<hostnames><hostname name="gentoo" type="PTR" /></hostnames>
<ports><extraports state="unknown" count="0" />
<port protocol="tcp" portid="21"><state state="open" /><service name="ftp" method="table" conf="3" /></port>
</ports>
</host>
<runstats><finished time="1147350477" timestr="Thu May 11 14:27:57 2006"/><hosts up="3" down="47" total="50" />
<!-- Nmap run completed at Thu May 11 14:27:57 2006; 50 IP addresses (3 hosts up) scanned in 1.898 seconds -->
</runstats></nmaprun>
Ich wollte es von oben nach unten auslesen und wenn der Port offen ist also state state="open" ist ich dann die dazugehörige IP-bekomme.

Danke schon mal
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Sonntag 14. Mai 2006, 20:26

pythonist hat geschrieben:dachte ich mir, es ist am einfachsten die XML-Datei zu parsen.
[...]
Ich wollte es von oben nach unten auslesen und wenn der Port offen ist also state state="open" ist ich dann die dazugehörige IP-bekomme.
Hi pythonist!

Nicht ganz einfach. Das gebe ich zu.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

from xml.dom.minidom import parseString

xml_string = """<?xml version="1.0" ?>
...
...
"""

parser = parseString(xml_string)

for host in parser.getElementsByTagName("host"):
    for port in host.getElementsByTagName("port"):
        for state in port.getElementsByTagName("state"):
            if state.hasAttribute("state"):
                if state.getAttribute("state") == "open":
                    for address in host.getElementsByTagName("address"):
                        if address.hasAttribute("addr"):
                            print address.getAttribute("addr")
Ohne eine gute Python-Shell wie zum Beispiel PyCrust, PyShell oder iPython kommt man da kaum weiter.

PyCrust
http://wxpython.org/PyManual.html#pycrust
PyShell
http://wxpython.org/PyManual.html#pyshell
PyCrust- und PyShell-Install
http://wxpython.org/download.php#binaries
iPython
http://ipython.scipy.org/
iPython-Screenshots
http://ipython.scipy.org/screenshots/index.html
iPython-Video
http://showmedo.com/videoListPage?listK ... thonSeries

Ich behelfe mir dann meist, indem ich mir zwischendurch immer wieder mit **dir()** die möglichen Befehle ansehe.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

from xml.dom.minidom import parseString

xml_string = """<?xml version="1.0" ?>
...
...
"""

parser = parseString(xml_string)

for host in parser.getElementsByTagName("host"):
    print dir(host)
    break
Da kommt dann so etwas raus:
['ATTRIBUTE_NODE', 'CDATA_SECTION_NODE', 'COMMENT_NODE', 'DOCUMENT_FRAGMENT_NODE', 'DOCUMENT_NODE', 'DOCUMENT_TYPE_NODE', 'ELEMENT_NODE', 'ENTITY_NODE', 'ENTITY_REFERENCE_NODE', 'NOTATION_NODE', 'PROCESSING_INSTRUCTION_NODE', 'TEXT_NODE', 'TREE_POSITION_ANCESTOR', 'TREE_POSITION_DESCENDENT', 'TREE_POSITION_DISCONNECTED', 'TREE_POSITION_EQUIVALENT', 'TREE_POSITION_FOLLOWING', 'TREE_POSITION_PRECEDING', 'TREE_POSITION_SAME_NODE', '__doc__', '__init__', '__module__', '__nonzero__', '__repr__', '_attrs', '_attrsNS', '_call_user_data_handler', '_child_node_types', '_get_attributes', '_get_childNodes', '_get_firstChild', '_get_lastChild', '_get_localName', '_get_tagName', '_magic_id_nodes', 'appendChild', 'attributes', 'childNodes', 'cloneNode', 'firstChild', 'getAttribute', 'getAttributeNS', 'getAttributeNode', 'getAttributeNodeNS', 'getElementsByTagName', 'getElementsByTagNameNS', 'getInterface', 'getUserData', 'hasAttribute', 'hasAttributeNS', 'hasAttributes', 'hasChildNodes', 'insertBefore', 'isSameNode', 'isSupported', 'lastChild', 'localName', 'namespaceURI', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', 'normalize', 'ownerDocument', 'paren
tNode', 'prefix', 'previousSibling', 'removeAttribute', 'removeAttributeNS', 'removeAttributeNode', 'removeAttributeNodeNS', 'removeChild', 'replaceChild', 'schemaType', 'setAttribute', 'setAttributeNS', 'setAttributeNode', 'setAttributeNodeNS', 'setIdAttribute', 'setIdAttributeNS', 'setIdAttributeNode', 'setUserData', 'tagName', 'toprettyxml', 'toxml', 'unlink', 'writexml']
Schon hat man wieder einen Überblick, was man mit **host** so alles machen kann. Und Befehle wie **hasAttribute**, **getAttribute**, **getElementsByTagName** sprechen ja fast schon wieder für sich.

Es gibt noch ein paar Pakete, die so etwas ein wenig vereinfachen sollen. Das sind zum Beispiel BeautifulSoup oder ElementTree.

mfg
Gerold
:-)

Edit: Ein paar Links hinzugefügt
Zuletzt geändert von gerold am Sonntag 14. Mai 2006, 22:10, insgesamt 3-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Sonntag 14. Mai 2006, 20:43

Wie man sieht wird es mit **BeautifulSoup** auch nicht unbedingt kürzer.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

from BeautifulSoup import BeautifulSoup

xml_string = """<?xml version="1.0" ?>
...
...
"""

soup = BeautifulSoup(xml_string)

for host in soup("host"):
    for port in host("port"):
        for state in port("state"):
            if state.get("state") == "open":
                for address in host("address"):
                    addr = address.get("addr")
                    if addr:
                        print addr
mfg
Gerold
:-)

Edit: Ein wenig ausgebessert.
Zuletzt geändert von gerold am Sonntag 14. Mai 2006, 21:03, insgesamt 3-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Sonntag 14. Mai 2006, 20:53

Ok, es geht mit **BeautifulSoup** ein wenig kürzer:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

from BeautifulSoup import BeautifulSoup
import re

xml_string = """<?xml version="1.0" ?>
...
...
"""

soup = BeautifulSoup(xml_string)

for host in soup("host"):
    for port in host("port"):
        for state in port("state", {"state": "open"}):
            for address in host("address", {"addr": re.compile('.*')}):
                print address["addr"]
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
pythonist
User
Beiträge: 40
Registriert: Sonntag 14. Mai 2006, 17:28

Sonntag 14. Mai 2006, 21:30

Danke erst mal für deine Arbeit, hier wird einem ja echt Klasse geholfen. Ich werds mogen mal durchgehen weil ich will das ganze ja auch verstehen.
Antworten