Schablone auf einen String anlegen

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
Benutzeravatar
tiax
User
Beiträge: 152
Registriert: Samstag 23. Juli 2005, 17:28
Kontaktdaten:

Hallo,

ich habe versucht, eine HTML-Seite nach einigen Informationen zu untersuchen und angefangen, es mit einem Parser zu versuchen. Das problem ist allerdings, dass die HTML-Seite nicht valide ist und wohl mit einem Wysiwyg-Editor gemacht worden ist - die Inhalte sind mit dutzenden Tabellen und leeren Zellen und so weiter eingeordnet und das Parsen macht nicht so recht Spaß. Zwischen den einzelnen Informationen steht dann oft auch noch ein <br> oder <b>. Jede Information steckt aber meist in ihrem eigenen "Design-Element", sprich der umgebende HTML-Code ist immer der gleiche. Ich hab mir also überlegt: Man legt ne Schablone an und übernimmt genau das, was in den Lücken steht. Meine ersten Versuche waren wild mit Schleifen durch .splitlines()-bearbeitete Strings und wieder .split('<br'>), also nicht sonderlich elegant.

Im tiefen Hinterkopf klingelte noch eine Glocke: Regexp. Aber man hat schon von so manchem gehört, der ein Problem mit Strings hatte und sich dachte "Hey ich habs, ich nehm einfach Regexp!" und sodann hatte er zum einen ein Problem mit Strings und zum anderen eines mit Regexp.

Bevor ich mich jetzt also in die wirren der Fingerbrechenden Regexp-Syntax vorwage, wollte ich fragen, ob das eine intelligente Idee ist oder ob die wirklich praktische Methode vielleicht wo ganz anders liegt. Wie wäre sowas denn am besten zu bewerkstelligen?
Ne invoces expellere non possis
[url=xmpp://florian@florianheinle.de]xmpp:florian@florianheinle.de[/url]
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Wie wärs mit:

http://www.python.org/doc/2.4.2/lib/module-htmllib.html

? Ich hab damit schon relativ einfach Inhalte aus Webseiten rauspulen können. Wenn Du ein Beispiel brauchst sag es, ich schreib gern schnell eins zusammen wenn ich heute abend wieder zu Hause bin.

--- Heiko.
Benutzeravatar
tiax
User
Beiträge: 152
Registriert: Samstag 23. Juli 2005, 17:28
Kontaktdaten:

Genau mit dem Modul hatte ich schon ein wenig rumgespielt (ohne jetzt aber was abzuspeichern, weils nicht funktioniert hat - wie gesagt, eigener Versuch war mit String-Manipulation), kam aber nicht so wirklich auf einen grünen Zweig damit

Zu analysieren wären Strings (wie etwa hier)

Code: Alles auswählen

<td bgcolor="#2A2A2A" align="right"><font color="CCCCCC">8.938 <br>6.857 </td>
oder

Code: Alles auswählen

<td bgcolor="#1A1A1A" align="right">
 <font color="#CCCCCC">Zielbasis <b>Exosphaere 13x113x7</b> </br>von [DN] Himmelskaiser 
</td>
damit hatte ich nicht so viel Freude. Ich bin mir nicht sicher gewesen, ob das wirklich geeignet ist, vor allem bei einigen HTML-Fehlern
Ne invoces expellere non possis
[url=xmpp://florian@florianheinle.de]xmpp:florian@florianheinle.de[/url]
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

htmllib ist sehr vergebend bei Fehlern. Und, ja, es ist definitiv dazu geeignet sowas zu parsen.

Wie gesagt, ich schreib Dir heute abend mal ein kleines Beispielprogramm dafür.

--- Heiko.
Benutzeravatar
tiax
User
Beiträge: 152
Registriert: Samstag 23. Juli 2005, 17:28
Kontaktdaten:

Gut, dann hatte ich wohl die falsche Herangehensweise, aber mit einem Beispiel werde ich wohl in der Lage sein, den richtigen Einstieg zu finden, danke sehr. Ich warte also artig darauf und werde damit dann versuchen, mein Projekt voranzutreiben
Ne invoces expellere non possis
[url=xmpp://florian@florianheinle.de]xmpp:florian@florianheinle.de[/url]
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Hier ein Beispiel welches den Inhalt des <b>-Tags aus dem <td> im zweiten Beispiel ausliest:

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

import HTMLParser

STATE_NONE, STATE_SPECIAL_TD, STATE_BCONTENT = range(3)

class MeinParser(HTMLParser.HTMLParser):

    def __init__(self):
        HTMLParser.HTMLParser.__init__(self)

        self._data = []
        self._state = 0

    def handle_starttag(self,tag,attrs):
        attrs = dict(attrs)
        if self._state == STATE_NONE:
            if tag == "td":
                if ( attrs.get("bgcolor",None) == "#1A1A1A" and
                     attrs.get("align",None) == "right" ):
                    self._state = STATE_SPECIAL_TD
        elif self._state == STATE_SPECIAL_TD:
            if tag == "b":
                self._state = STATE_BCONTENT
        elif self._state == STATE_BCONTENT:
            pass

    def handle_endtag(self,tag):
        if self._state == STATE_NONE:
            pass
        elif self._state == STATE_SPECIAL_TD:
            if tag == "td":
                self._state = STATE_NONE
        elif self._state == STATE_BCONTENT:
            if tag == "b":
                self._state = STATE_SPECIAL_TD
                print "Inhalt des B-Tags in speziellem td:", \
                      repr(u"".join(self._data))
                self._data = []

    def handle_data(self,data):
        if self._state == STATE_NONE:
            pass
        elif self._state == STATE_SPECIAL_TD:
            pass
        elif self._state == STATE_BCONTENT:
            self._data.append(data)

    def handle_charref(self,name):
        if self._state == STATE_NONE:
            pass
        elif self._state == STATE_SPECIAL_TD:
            pass
        elif self._state == STATE_BCONTENT:
            self._data.append(unichr(int(name[1:])))

    def handle_entityref(self,name):
        if self._state == STATE_NONE:
            pass
        elif self._state == STATE_SPECIAL_TD:
            pass
        elif self._state == STATE_BCONTENT:
            self._data.append(htmlentitydefs.name2codepoint[name])

data = """
<td bgcolor="#1A1A1A" align="right">
 <font color="#CCCCCC">Zielbasis <b>Exosphaere 13x113x7</b> </br>von [DN] Himmelskaiser 
</td>
"""

x = MeinParser()
x.feed(data)
x.close()
Das ganze ist im Endeffekt eine state-machine, die vom tokenizer (HTMLParser.HTMLParser) mit aufrufen gefüttert wird. Du kannst dem im Endeffekt beliebig komplex machen, mußt Dir nur darüber im klaren sein wann was aufgerufen wird. Wenn Du dann den Inhalt eines bestimmten Tags ausgelesen hast kannst Du diesen mit Regexes weiterbearbeiten.

Hoffe das hilft!

--- Heiko.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Zum HTMLParser stehen bestimmt noch einige Beispiele hier im Forum! Also einfach mal nach suchen :)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

tiax hat geschrieben:ich habe versucht, eine HTML-Seite nach einigen Informationen zu untersuchen und angefangen, es mit einem Parser zu versuchen. Das problem ist allerdings, dass die HTML-Seite nicht valide ist
Hi tiax!

Ich habe noch nicht versucht, mit BeautifulSoup eine nicht valide HTML-Seite zu parsen. Falls es funktioniert, gibt es kaum eine einfachere Möglichkeit, eine HTML-Seite zu parsen.

Siehe: http://www.python-forum.de/viewtopic.php?t=4664

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
tiax
User
Beiträge: 152
Registriert: Samstag 23. Juli 2005, 17:28
Kontaktdaten:

Hi,

danke für eure Bemühungen, ich kam jedoch nicht so gut zurecht mit den Parsern, am Ende habe ich doch wieder an den Strings rumbauen müssen, nachdem ich geparsed habe.

Das Problem habe ich jetzt aber mit Regexp gelöst, nachdem ich mir das Howto dazu nochmal angeschaut habe.

War nicht schwer, gereicht haben 3 Ausdrücke:
startregexp = compile(r'Startbasis <b> (.+)</b></br>&nbsp;von ?(\[.+\])? ?(.+)&nbsp;')
zielregexp = compile(r'Zielbasis <b> (.+)</b> </br>von&nbsp; ?(\[.+\])? ?(.+)&nbsp;')
uhrzeitregexp = compile(r'Zeit <b>(\d+.\d+.\d+) (\d+:\d+:\d+.*)</b>')
Mit startregexp.search(ganzerhtmlinhalt).groups() kriegt man dann ein Tuple in dem alles schön drin steht. Ist vielleicht nicht so effizient, jedoch wird das Script weder häufig ausgeführt noch sind die Berichte besonders lang.
Ne invoces expellere non possis
[url=xmpp://florian@florianheinle.de]xmpp:florian@florianheinle.de[/url]
Antworten