findall für Anfänger

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.
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

Hallo,

ich versuche seit Tagen, aus einer Website einzelne Infos auszulesen.
Es gibt zum Beispiel 5 mal eine solche Zeile:
<td class="odd preis_his">48,85 €</td>

ich versuche es (try and error) zum Beispiel so (habe extra die Sonderzeichen <>"& erst mal rausgelassen):

Code: Alles auswählen

import os, sys
from twisted.web.client import getPage
from twisted.internet import reactor
from re import sub, split, search, match, findall
from string import find, atoi, strip
import urllib, os, sys, tempfile

website = urllib.urlopen("http://www.test.php")
Zeilen = website.readlines()
res = findall(r'odd([^euro]*)', Zeilen)
res2 = = "%s %s %s %s %s %s" % (x[0],x[1],x[2],x[3],x[4],x[5])
print res2
ich vermute, da ist wohl mehr als nur ein Fehler drin?

sowas funktioniert in einem fremden script:

Code: Alles auswählen

x = findall(r'/bilder/zahlen/.*/(?P<zahlen>\d.*)\.gif',output
)



ja, ich habe die Suche benutzt (bin jetzt eher verwirrter als vorher)
nein, google hat moch nicht schlauer gemacht
sorry, bin absoluter Python-Anfänger und durch bisheriges arbeiten mit VB und ähnlichem tue ich mich sehr schwer
BlackJack

@shadow07: Ja da ist mehr als ein Fehler drin. Mindestens ein Syntaxfehler und ein `NamenError` in Zeile 11. Man kann nicht einfach zwei Gleicheitszeichen hintereinander schreiben, oder auf Namen zugreifen, die vorher nicht definiert wurden.

Bitte demnächst lauffähiges und möglichst minimales als Beispiel zeigen. Du hast da nämlich auch eine Menge Importe, die gar nicht verwendet werden.

Die Importe aus `string` sollte man auch nicht verwenden. `find()` und `strip()` sind als Methoden auf Zeichenketten vorhanden und statt `atoi()` kann man `int()` verwenden.

Der reguläre Ausdruch passt auf 'odd' gefolgt von beliebig vielen Zeichen, die nicht 'e', 'u', 'r', oder 'o' sind. Damit kommst Du in dem Beispiel genau bis zu dem 'p' von 'preis_his', weil danach eben ein 'r' kommt.

HTML mit regulären Ausdrücken zu vearbeiten ist aber auch keine so gute Idee. Benutze dafür lieber eine Bibliothek, die HTML versteht und genau für solche Aufgaben gedacht ist, wie `BeautifulSoup` oder `lxml.html`.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo,

beim Parsen von Webseiten nicht mit RegExps arebeiten! Wir haben das Thema gefühlte 3x die Woche :-D

Such einfach mal per SuFu hier. Du machst das am besten mit lxml oder html5lib. Das wird in vielen Threads ausführlich erklärt!

Wollte zu dem Thema nicht mal irgend wer einen Beitrag im wiki schreiben oder in der FAQ?
Panke
User
Beiträge: 185
Registriert: Sonntag 18. März 2007, 19:26

Mit Beautifulsoup:

Code: Alles auswählen

soup = BeautifulSoup(seiten_text)
tds = soup.findAll('td', class="odd_preis_his")
Mit der Übergabe des class-Attributes bin ich mir nicht sicher, schau mal in der Doku nach.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hyperion hat geschrieben:Wollte zu dem Thema nicht mal irgend wer einen Beitrag im wiki schreiben oder in der FAQ?
In der FAQ ist doch ein Abschnitt. Ich kann ja nichts dafür das die niemand liest.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Leonidas hat geschrieben:
Hyperion hat geschrieben:Wollte zu dem Thema nicht mal irgend wer einen Beitrag im wiki schreiben oder in der FAQ?
In der FAQ ist doch ein Abschnitt. Ich kann ja nichts dafür das die niemand liest.
Ah ... da isser ja :-)
[wiki]FAQ#WieVerarbeiteIchWebseiten[/wiki]
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

zuerst mal vielen Dank dafür, das ihr immer wieder durchgekaute Themen jedesmal neu zu erklären versucht.
1. xml-Parser fallen glaube ich aus, da die Seite dynamisch erstellt wird

2. ich habe kein lauffähiges script, ich habe ein script erstellt:
#!/bin/sh

wget -q "http://www.esyoil.com/heiz%C3%B6lpreise ... tal_e3.php" -O /tmp/heizoel3.txt

sed '{s/<[^>]*>//g;s/&euro;//g;s/&nbsp;//g;s/Heute//g;s/^[ \t]*//;1,134d;194,$d;137d;138d}' /tmp/heizoel3.txt >/tmp/datei01.txt

sed '{/^\s*$/d;s/^[ \t]*//;s/+/%2B/g;s/-/%2D/g}' /tmp/datei01.txt >/tmp/datei09.txt

a=$(sed -n '1p' datei09.txt)",%20%20"$(sed -n '2p' datei09.txt)
b="2000=%20%20%20"$(sed -n '3p' /tmp/datei09.txt)"%20%20%2F%20%20"$(sed -n '4p' /tmp/datei09.txt)"%20%20"$(sed -n '5p' datei09.txt)
c="2500=%20%20%20"$(sed -n '6p' /tmp/datei09.txt)"%20%20%2F%20%20"$(sed -n '7p' /tmp/datei09.txt)"%20%20"$(sed -n '8p' datei09.txt)
d="3000=%20%20%20"$(sed -n '9p' /tmp/datei09.txt)"%20%20%2F%20%20"$(sed -n '10p' /tmp/datei09.txt)"%20%20"$(sed -n '11p' datei09.txt)
e="3500=%20%20%20"$(sed -n '12p' /tmp/datei09.txt)"%20%20%2F%20%20"$(sed -n '13p' /tmp/datei09.txt)"%20%20"$(sed -n '14p' datei09.txt)
f="4000=%20%20%20"$(sed -n '15p' /tmp/datei09.txt)"%20%20%2F%20%20"$(sed -n '16p' /tmp/datei09.txt)"%20%20"$(sed -n '17p' datei09.txt)

wget "http://127.0.0.1/web/message?text=$c%0a ... &timeout=0" 2>/dev/null

dieses script benötige ich aber in Python, von welchem ich bis vor kurzem nicht mal was gehört habe
also habe ich versucht, aus anderen py-scripten zu erkennen, wie die von mir gewünschten Funktionen umgesetzt werden können, habe dann in den leider fast ausschließlich englischen Dokus endlos gesucht, ein paar hundert mal 'try and error' gespielt und mich nun entschlossen, euch um Hilfe zu bitten (Script-Sprachen nach Buch zu lernen ist mir noch nie gelungen, ich habe mir Beispiele gesucht, geändert und aus den Fehlern gelernt, aber hier stehe ich diesmal komplett auf dem Schlauch weil ich absolut keinen Plan hab und keinen Anfang finde)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

shadow07 hat geschrieben:1. xml-Parser fallen glaube ich aus, da die Seite dynamisch erstellt wird
Und wo ist das Problem? Ob die Seite dynamisch erzeugt wird ist komplett egal, das solltest du aber auch bemerkt haben, denn dein Shell Skript bearbeitet auch eine statische Seite ;) Nebenbei ist Beautiful Soup ein HTML Parser.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Der FAQ-Eintrag sagt schon eigentlich alles was du brauchst: einen Parser (ich rate zu html5lib oder lxml.html) und du musst wissen was du aus dieser Seite auslesen willst (mit lxml ist es dann sehr einfach, da man einen CSS-Selektor nutzen kann oder wenn man etwas aufwändigeres haben will auch XPath einsetzen kann um einen bestimmten Knoten aus einer Seite auszulesen. Ist aber mit etwas spielerei in der Konsole (Interpreter nutzen!) durchaus machbar und simpel.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Leonidas hat geschrieben:... oder wenn man etwas aufwändigeres haben will auch XPath einsetzen kann um einen bestimmten Knoten aus einer Seite auszulesen. Ist aber mit etwas spielerei in der Konsole (Interpreter nutzen!) durchaus machbar und simpel.
Es gibt da ja auch einige nützliche Firefox-Plugins, mit denen man die XPath Ausdrücke an der Seite testen kann - die finde ich in dem Zusammenhang durchaus nützlich. Aber klar, rein in einer Konsole geht's natürlich auch.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich für meinen Teil nutze wo es geht die CSS-Selektoren in der Konsole. Das hat den Vorteil dass es simpler ist (man braucht selten die vollen Möglichkeiten von XPath, da kann man zur Not auch mit Python das Ergebnis nochmal filtern) und dass ich genau das als Rausbekomme was das Skript dann auch rausbekommen sollte. Das spart Probleme bei Inkompatibilitäten (ich weiß nicht wie gut der Support von XPath in Firefox und lxml jeweils ist). Das es da Firefox-Plugins gibt wusste ich aber noch gar nicht. Wenn ich sowas genutzt habe, dann höchstens via jQuery + Firebug :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

@BlackJack
vielen Dank für die konstruktive Hilfe, ich habe etwas aufgräumt, string-import entfernt und weiterprobiert und gelesen, ich komm auf keinen Zweig, ich kapiere den Aufbau der findall-Anweisung nicht

Code: Alles auswählen

#!/usr/bin/python
 
from twisted.web.client import getPage
from re import sub, split, search, findall, IGNORECASE
 
seite=getPage('http://www.esyoil.com/heiz%C3%B6lpreise/heiz%C3%B6l_Obermarchtal_e3.php')
x = findall(r'preis_his(?)',seite)
print x
das wichtigste, was ich im Moment brauche, ist die Syntax erklärt für doofe, ungefähr
x= findall(r'ab hier suchen(nicht suchen)das hier suchen', hier drin suchen)

@alle anderen
es ist zwar schön das man mir helfen will, aber bitte nicht nach dem Motto 'wie a funktioniert sagen wir nicht, benutze b'
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

shadow07 hat geschrieben:es ist zwar schön das man mir helfen will, aber bitte nicht nach dem Motto 'wie a funktioniert sagen wir nicht, benutze b'
Warum nicht? Kennst du Module wie lxml überhaupt? Bei Python lauet das Motto: "Batteries included". Natürlich kannst du weiterhin versuchen, die Seite mit dem re-Modul zu parsen. Ob dir viele Leute dabei helfen wollen, weiß ich allerdings nicht. Aufgeschlossenheit und Flexibilität sind für eine gute Lösung (ist nicht unbedingt das gleiche wie funktionierende) notwendig.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

shadow07 hat geschrieben:@alle anderen
es ist zwar schön das man mir helfen will, aber bitte nicht nach dem Motto 'wie a funktioniert sagen wir nicht, benutze b'
"a" funktioniert nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und keinen Parser verwenden wollen, dafür aber getPage aus Twisted nehmen, obwohl Python sowohl ``urllib`` als auch ``urllib2`` hat ist auch irgendwie inkonsequent :roll: Aber vielleicht hat der OP ja irgendwelche sinnvollen Gründe dafür. Vielleicht mag er die uns sogar nennen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

Aber vielleicht hat der OP ja irgendwelche sinnvollen Gründe dafür. Vielleicht mag er die uns sogar nennen
er nennt: ich habe in den letzten Tagen ein paar 100 Zeilen Code ausprobiert (ja, totales rumgestümper), darunter auch urllib wie in meinem ersten Post zu sehen war. Ich kann zur Zeit weder die Unterschiede noch die Wirksamkeiten beurteilen. Außerdem handelt es sich nicht um einen PC, eventuell soll die Lösung später auch anderen zugänglich gemacht werden, deshalb möchte ich nichts zusätzliches installieren müssen für die Lösung
"a" funktioniert nicht.
die Beispielzeile aus meinem ersten Post ist einem laufenden Script entnommen, also das es nicht funktioniert entspricht schlicht nicht der Wahrheit


ansonsten kann ich nur erstaunt feststellen: es wurde hier sehr oft auf den Button 'Antworten' geklickt und einiges an Text eingegeben, geantwortet hat mir außer dem ersten jedoch niemand. Schade um die Zeit der Poster (hilft weder mir noch ihnen).
Ich habe viele Stunden im Internet gesucht und eine Menge erklärender Seiten gefunden, leider alles englisch und somit für mich schlecht bis gar nicht verständlich (und solange ich keinen Zugang zur Funktionsweise Linux/Python finde kann ich mir da auch nichts zusammenreimen wie es mir bei php, VB und anderem bisher immer gelungen ist)

ich habe hier nicht nach einer fertigen Lösung gefragt, kein komplettes Script erbeten - da könnt ich die Reaktionen verstehen
Es kann allerdings auch sein, das entgegen älteren Beiträgen in diesem Board inzwischen nur noch Leuten geholfen wird, welche Python beherrschen (das sollte man mir aber mitteilen, dann melde ich mich hier eben wieder ab da im falschen Board)
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

shadow07 hat geschrieben:
Aber vielleicht hat der OP ja irgendwelche sinnvollen Gründe dafür. Vielleicht mag er die uns sogar nennen
er nennt: ich habe in den letzten Tagen ein paar 100 Zeilen Code ausprobiert (ja, totales rumgestümper), darunter auch urllib wie in meinem ersten Post zu sehen war. Ich kann zur Zeit weder die Unterschiede noch die Wirksamkeiten beurteilen. Außerdem handelt es sich nicht um einen PC, eventuell soll die Lösung später auch anderen zugänglich gemacht werden, deshalb möchte ich nichts zusätzliches installieren müssen für die Lösung
urllib2 ist Teil der Standardbibliothek, schon... seit ewigkeiten. Gibt keinen Grund dagegen... Es ist sogar kompatibel mit Python 3.0
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

och menno

Code: Alles auswählen

#!/usr/bin/python
 
#from twisted.web.client import getPage
from re import sub, split, search, findall, IGNORECASE
 
seite = urllib.urlopen("http://www.test.php")
x = findall('\d+\d+[,.]\d+|\d+',seite)
print x
gibt: File "/usr/lib/python2.5/re.py", line 167, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer

der Such-String ist direkt abgeschrieben, an vielen Stellen ähnlich gesehen, der kann doch einfach nicht fehlerhaft sein[/quote]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

``seite`` ist nun mal kein String. Den Inhalt der Seite gibt es mit ``seite.read()``. Siehe Dokumentation.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
shadow07
User
Beiträge: 43
Registriert: Sonntag 22. Februar 2009, 16:29

soweit bin ich nun:

Code: Alles auswählen

#!/usr/bin/python

from re import sub, split, search, findall, IGNORECASE
import urllib
 
seite = urllib.urlopen("http://www.esyoil.com/heiz%C3%B6lpreise/heiz%C3%B6l_Obermarchtal_e3.php")
seite2 = seite.read()
seite.close()

such = "odd preis_his"
anfpos = seite2.find(such)

nextpos = anfpos + 15


x = findall('\d{2}\,\d{2}',seite2)

print "2000 Liter, neuer Preis: " + x[0] + ",alter Preis: " + x[1] + " gesamt: " + str(float(x[0].replace(',','.'))*20) + "0"
print "2500 Liter, neuer Preis: " + x[2] + ",alter Preis: " + x[3] + " gesamt: " + str(float(x[2].replace(',','.'))*25) + "0"
print "3000 Liter, neuer Preis: " + x[4] + ",alter Preis: " + x[5] + " gesamt: " + str(float(x[4].replace(',','.'))*30) + "0"
print "3500 Liter, neuer Preis: " + x[6] + ",alter Preis: " + x[7] + " gesamt: " + str(float(x[6].replace(',','.'))*35) + "0"
print "4000 Liter, neuer Preis: " + x[8] + ",alter Preis: " + x[9] + " gesamt: " + str(float(x[8].replace(',','.'))*40) + "0"
der code macht was er soll, obwohl mit Sicherheit Verrenkungen drin sind die Profis besser wissen (?)

interessant für mich wäre: wie kann ich das komma ersetzten durch einen Punkt (zum berechnen) und anschließend wieder mit Komma austausche ohne ellenlange Code?
wie bekomme ich zwei Stellen nach dem Komma ohne selbst eine '0' hinzuschreiben?
Antworten