Zahlen aus HTML extrahieren

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
kritz
User
Beiträge: 13
Registriert: Montag 2. April 2007, 15:26

hallo

ich möchte in einer funktion aus folgendem html-code eine zahl extrahieren:

Code: Alles auswählen

<tr class=t2 height=30 valign=top>
  <td rowspan=2 class=s align=right>225,89<p align=right></td>

  <td rowspan=2 class=s align=center><a target=_blank href="/redir.cgi?h=it-designworks&loc=http:%2F%2Fwww.haym.info%2FSHOP%2Findex.html%3Fartikelnr%3D6A03198"><b>it-designworks (haym.infotec)</b></a><p><center><small><p><div align=right><nobr><a href="./?qlink=it-designworks%20%28haym.infotec%29&subi=infos">Infos</a> <a href="/redir.cgi?h=it-designworks&loc=http%3A%2F%2Fwww.haym.info%2FSHOP%2Fagb.htm" target=_blank>AGB</a> <a href="http://forum.geizhals.at/search.jsp?k=&author=&topic=%22%7Eit%5B%20-%5D%2Adesignworks%20%28haym%22&area=1&maxAge=0">Meinungen</a></nobr></div></td>
  <td rowspan=2 class=s align=center><p><a href="./?sb=555"><img border=0 valign=absmiddle vspace=2 src=http://geizhals.at/b/1_ani.gif alt="Note: 1,21" title="Note: 1,21 - Spitze!"></a><br><small>Note: 1,21</small><p class=x><small><a href="./?sb=555">708</a> Bewertungen</small><p></td>
  <td class=s width=150>nicht verfügbar</td>

  <td rowspan=2 class=s width="75%">Acer AM.<wbr>K0203.<wbr>001<br>Acer - Acer CI-<wbr>8330 (AM.<wbr>K0203.<wbr>001) (AM.<wbr>K0203.<wbr>001)<br>(Art# 6A03198)<p>(02.04.2007, 12:10)</td>
</tr>
Dazu habe ich folgendes geschrieben:

Code: Alles auswählen

    def auswerten(self):
        
        re1 = compile('<tr>.*?' + 'it-designworks' + '.*?</tr>') # Damit suche ich mir den teil, in welchem "It-designworks" vorkommt...das ist der oben angegebene teil
        re2 = compile('\d+<p align=right></td>') # damit suche ich zahlen, die vor dem text "<p align=right></td>" stehen
        re3 = compile('\d+') #damit hole ich mir die zahl
        zeile = re1.findall(self.htmltext)
        letztesStueck = re2.findall(zeile)
        return re3.findall(letztesStueck)
Ich erhalte die Fehlermeldung:
File "test5.py", line 24, in auswerten
letztesStueck = re2.findall(zeile)
TypeError: expected string or buffer

WARUM?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo kritz, willkommen im Forum,

Welche Zahl willst du nochmal extrahieren? Denn ich denke, es ist für mich einfacher den Code neu zu schrieben, als deinen Code zu verstehen.

In der Regel ist es auch eine schlechte Idee HTML mit Regulären Ausdrücken zu parsen - dafür eigenen sich Scraper-Tools wie BeautifulSoup wesentlich besser. Du solltest überlegen ob du nicht besser BeeautifulSoup einsetzen kannst, denn damit ist die Arbeit oft einfacher und zuverlässiger.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
kritz
User
Beiträge: 13
Registriert: Montag 2. April 2007, 15:26

ich hätte gerne die Zahl 225,89 (steht eh fast am anfang)

ich ein ähnliches skript gefunden, wo das so gemacht wird. deshalb hab ich diesen weg gewählt.

wichtig ist, dass das html file sehr groß ist. ich möchte die zahl aus jenem tag, wo ein bestimmter Text (z.B. "it-designworks (haym.infotec)") vorkommt.

danke
BlackJack

Mit `BeautifulSoup` könnte man so vorgehen: Den Text suchen. Von dort aus das umschliessende ``tr``-Tag suchen und von da dann auf den Inhalt des ersten ``td``-Tags zugreifen:

Code: Alles auswählen

import re
from BeautifulSoup import BeautifulSoup


def main():
    html_file = open('test.html')
    soup = BeautifulSoup(html_file.read())
    html_file.close()
    
    text_node = soup.find(text=re.compile('it-designworks'))
    tr_node = text_node.findParent('tr')
    print tr_node.td.contents[0]
kritz
User
Beiträge: 13
Registriert: Montag 2. April 2007, 15:26

ich hab mich schon herumgespielt, aber das "findParent" hat mir noch gefehlt....DANKE
kritz
User
Beiträge: 13
Registriert: Montag 2. April 2007, 15:26

Ich möchte gerne das ganze Objektorientiert gestalten, d.h. ich hätte gerne eine Klasse "Abfrage" mit den entsprechenden Methoden.

Wie kann ich jetzt von HTML aus die KLasse instanzieren, die suche starten und das Ergebnis an HTML zurückliefern?

Code: Alles auswählen

#! D:\Programme\Python25\python.exe
import cgi
import urllib2
from BeautifulSoup import BeautifulSoup
import re

class Abfrage:
    def __init__(self)
        url = "test.html"
        produkt = "it-designworks"
        page = urllib2.urlopen(url)
        soup = BeautifulSoup(page)

    def __search__(self)
        text_node = soup.find(text=re.compile(produkt))
        tr_node = text_node.findParent('tr')
        preis = tr_node.td.contents[0]

import cgitb
cgitb.enable()
print 'Content-type: text/html'
print
print '<html>'
print '<head><title>Abfrage</title></head>'
print '<body>'
print '<h3> Der Preis betraegt', preis, ' </h3>'
print '</body>'
print '</html>'

BlackJack

Was genau soll die Klasse denn bringen? Du teilst da völlig ohne Notwendigkeit eine einfache Funktion auf zwei Methoden auf. Das macht das ganze einfach nur komplizierter ohne einen Mehrwert.
kritz
User
Beiträge: 13
Registriert: Montag 2. April 2007, 15:26

ich habe bereits einige weitere dateien, wo ich dann die preise abspeichere. diese sind dann viel umfangreicher und ich hab mir gedacht, dass das ganze dann übersichtlicher aussieht. oder soll ich es lieber so lassen?

mich würds auch interessieren, wie es funktioniert!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

kritz hat geschrieben:idiese sind dann viel umfangreicher und ich hab mir gedacht, dass das ganze dann übersichtlicher aussieht. oder soll ich es lieber so lassen?
Nein, dadurch Komplizierst du die Sache nur unnötig - statt einer Funktion mit Rückgabewert hast du nun eine Klasse, die du instanziieren musst, eine Funktion mit seltsamen Namen aufrufen musst und dann dern Preis isrgendwo aus deren Interna rausholen. Mehrwert hast du dadurch überhaupt keinen. Außer dass es nun einfacher nach Java portiert werden kann ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten