Seite 1 von 1

HTMLparser nächstes Tag finden

Verfasst: Montag 1. Oktober 2012, 21:39
von error1
Hallo,
ich bin recht unerfahren in python und Programmieren allgemein. Für kleinere Scripts reicht es jedoch noch.

Nun stehe ich vor der Aufgabe HTML mittles html.parser zu parsen (Python 3).

Ich schaffe es Text „Text1“ zu Filter bei Tags in der Form von:

<td class="Class1"> Text1 </td>

Indem ich Tags <td> mit class “Class1” filtere und mittels

def handle_data(self, data):
print(data)

rausschreibe

Nun kommt es vor das in der HTML außerdem Sachen in der Form von:

<td class="ClassB”> Some Text</td>
<td class="ClassB”> Some Text1</td>
<td class="ClassB”> Some Text2</td>
.
.
</tr>
<tr class="new"><td class="ClassA">Text A</td>
<td class="ClassB”> Text Eins A</td>
</tr>
</tr>
<tr class="new"><td class="ClassA">Text A</td>
<td class="ClassB”> Text Eins B</td>
</tr>

Nun kann ich das Script davor nicht nutzen das ClassB öfter vorkommt ich jedoch nur den Text brauche (Text Eins) wenn „Text A“ in dem Feld davor steht.
Wäre es möglich class „new“ zu filtern und sich dann zwei Tags runter zu hangeln?
Habe da leider nichts gefunden

Gruß und Danke
Error1

Re: HTMLparser nächstes Tag finden

Verfasst: Montag 1. Oktober 2012, 23:25
von BlackJack
@error1: Ich würde da eher einen Parser verwenden der mit real existierendem HTML klar kommt und auch eine einfachere Navigation im Ergebnis erlaubt. `lxml.html` oder `BeautifulSoup` sind dafür geeignet. Ich weiss allerdings nicht ob und welcher davon für Python 3 verfügbar ist.

Re: HTMLparser nächstes Tag finden

Verfasst: Dienstag 2. Oktober 2012, 05:49
von sparrow
lxml funktioniert mit Python 2.x und Python 3.x

Beautiful Soap 4 ebenso.

Re: HTMLparser nächstes Tag finden

Verfasst: Dienstag 2. Oktober 2012, 07:27
von BlackJack
Na dann kann man sich ja zum Beispiel für `lxml` entscheiden und hat dort die Auswahl zwischen `cssselect()` und `xpath()`. Falls ich die Kriterien richtig verstanden habe:

Code: Alles auswählen

from lxml import html


def main():
    root = html.parse('test.html').getroot()
    # 
    # Variante 1
    # 
    nodes = (
        n.itersiblings('td').next()
        for n in root.cssselect('tr.new td.ClassA')
        if n.text == 'Text A'
    )
    result = [n.text.strip() for n in nodes if n.get('class') == 'ClassB']
    print result
    # 
    # Variante 2
    # 
    result = [
        s.strip() for s in root.xpath(
            '//tr[@class="new"]'
            '/td[@class="ClassA" and text()="Text A"]'
            '/following-sibling::td[@class="ClassB"][1]'
            '/text()'
        )
    ]
    print result


if __name__ == '__main__':
    main()

Re: HTMLparser nächstes Tag finden

Verfasst: Dienstag 2. Oktober 2012, 13:46
von error1
Hallo,

vielen dank für die anregungen. Habe sowas schon vermutet.
Ich werde es mal mit lxml versuchen.

Der Test ode an im Schnelltest nicht funktioniert aber ich werde mich mal in lxml einlesen und gucken ob ich es zustande bekommen. Ansonsten melde ich mich bestimmt nochmal.

Gruß

EDIT: hab sowas ähnliches wie deine xpath variante erstellt. funktioniert bestens. Danke

Re: HTMLparser nächstes Tag finden

Verfasst: Sonntag 7. Oktober 2012, 20:17
von error1
Hi,

ich stehe nun vor folgendem problem ich habe tags in derform von

<td class="ClassA"> Text <a href="..."> Zusatz </a></td>

wie kriege ich denn nur "Text Zusatz" raus.

Es würde funktionieren mit a = tree.xpath( //td[@class="ClassA"]/text())
was "Text" auswirft
+
b = tree.xpath(//td[@class="ClassA"]/a/text())
was "Zusatz" auswirft
und dann zusammenfügen

Nun kommt es aber vor das manchmal
<td class="ClassA"> Text1 <a href="..."> Zusatz1 </a></td>
...
<td class="ClassA"> Text2 </td>
...
<td class="ClassA"> Text3 <a href="..."> Zusatz3 </a></td>

im html steht.
Da würde ja dann 2 Listen mit ungleicher Länge ausgeben.

Gibt hier ne leichte Lösung?

Gruß


da steht

Re: HTMLparser nächstes Tag finden

Verfasst: Sonntag 7. Oktober 2012, 21:50
von BlackJack
@error1: Suche nur nach den Knoten mit der gewünschten CSS-Klasse und rufe auf denen dann die `text_content()`-Methode auf.