Html Seite einlesen
- __blackjack__
- User
- Beiträge: 13004
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@egon11: Doch, aber Du musst halt sicherstellen das entweder Unicodezeichenketten in Unicodezeichenketten oder Bytezeichenketten in Bytezeichenketten formatiert werden. Am saubersten ist es für Text `unicode` zu nehmen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Code: Alles auswählen
import requests
from bs4 import BeautifulSoup
url = "http://www.sportal.de/fussball/bundesliga/tabelle/tabelle-saison-2019-2020"
response = requests.get(url)
html = BeautifulSoup(response.content, 'lxml')
tabelle = html.find(class_="table_content")
liste = []
beschreibung = "{0:<4} {1:<22} {2:>4} {3:>4} {4:>4} {5:>4} {6:>7} {7:>4} {8:>4} ".format("Pl", "Verein", "Sp", "G", "UE", "V", "Tore", "Diff", "P") + "\n\n"
liste.append(beschreibung)
for row in tabelle.find_all("ul"):
meintext = [d.unicode for d in row.find_all("li")]
text_fertig = "{0:<4} {1:<22} {2:>4} {3:>4} {4:>4} {5:>4} {6:>7} {7:>4} {8:>4} ".format(meintext[0],meintext[2],meintext[3],meintext[4],meintext[5],meintext[6],\
meintext[7],meintext[8],meintext[9]) + "\n"
liste.append(text_fertig.encode('utf8'))
print("".join(liste))
Das encode habe ich wieder raus genommen. so sieht meine print Ausgabe aus:
Code: Alles auswählen
Pl Verein Sp G UE V Tore Diff P
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
None None None None None None None None None
Jetzt sehe ich erst, was Du gemacht hast. Du hast d.text durch d.unicode ersetzt. Wie kommst Du nur auf die Idee, dass das was sinnvolles sein könnte. Mit Raten kommst Du nicht weiter. Also entweder Du liest die Dokumentation oder befolgst das, was Dir hier empfohlen wird.
Wie schon gesagt wurde: response.content liefert Bytes, aber in so einem Fall will man Unicode. Also muss man "text" statt "content" benutzen. Teilt man es außerdem zur Übersicht und Testbarkeit in Funktionen auf und zieht die konfigurierbaren Teile an den Anfang, dann kann das so aussehen:
Code: Alles auswählen
#!/usr/bin/env python3
from bs4 import BeautifulSoup
import requests
URL = "http://www.sportal.de/fussball/bundesliga/tabelle/tabelle-saison-2019-2020"
TABLE_CONFIG = {
"Pl": "<4",
"Verein": "<22",
"Sp": ">4",
"G": ">4",
"UE": ">4",
"V": ">4",
"Tore": ">7",
"Diff": ">4",
"P": ">4",
}
def get_table_soup(url):
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, "lxml")
return soup.find(class_="table_content")
def parse_table_rows(soup):
for row in soup.find_all("ul"):
yield [elem.text.strip() for elem in row.find_all("li")
if not elem.text.isspace()]
def print_table(rows, config):
template = " ".join(f"{{:{spec}}}" for spec in config.values())
print(template.format(*config.keys()))
for row in rows:
print(template.format(*row))
def main():
rows = parse_table_rows(get_table_soup(URL))
print_table(rows, TABLE_CONFIG)
if __name__ == '__main__':
main()
- __blackjack__
- User
- Beiträge: 13004
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@snafu: Ob man `text` oder `content` nimmt ist eigentlich egal denn das geht ja in jedem Fall durch den HTML-Parser und danach ist es `unicode`, egal was man da rein gefüttert hat. Das war ja das Problem, das versucht wurde die `unicode`-Objekte die BeautifulSoup liefert in ein `str`-Objekt zu formatieren. Und das Problem hat Dein Code auch, wenn er denn überhaupt unter Python 2 laufen würde.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
@snafu: das ist nicht das Problem. Denn wenn BeautifulSoup ein Bytes-Objekt bekommt, dann ermittelt es das Encoding wenn möglich am meta-Tag. Außerdem geht es gerade darum, das mit Python2 zum Laufen zu bringen. Da kann man sich nicht auf die Reihenfolge von Wörterbüchern verlassen oder f-Strings benutzen.
response.content führt in der cmd.exe unter Windows jedenfalls zu Darstellungsproblemen mit Umlauten. Bei response.text besteht das Problem nicht. Für Python 2.7 habe ich es jetzt nicht getestet. Die neuen Features gehen da natürlich nicht. Fragt sich dann aber eher, warum jemand noch Python 2.x nutzt und ob er kein Upgrade machen kann...
- __blackjack__
- User
- Beiträge: 13004
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@snafu: *Die* Frage wurde auch schon gestellt und beantwortet: Das soll ein Plugin für Enigma2 sein, und da gibt's halt nur Python 2. Das zu ändern dürfte den Rahmen sprengen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
lxml ist bestimmt schneller, aber der Grund dafuer ist, dass es ein wrapper um die C-Bibliotheken libxml und libxslt ist. Sind die auf deiner enigma vorhanden? Sonst ist das alles vergebliche Liebesmueh.
Und so oder so frage ich mich, warum du hier rumoptimieren willst. Es fallen ja keine Tore im Mikrosekunden-Takt. Wenn es ein paar Sekunden dauert, das zu updaten - wo liegt genau das Problem?
Und so oder so frage ich mich, warum du hier rumoptimieren willst. Es fallen ja keine Tore im Mikrosekunden-Takt. Wenn es ein paar Sekunden dauert, das zu updaten - wo liegt genau das Problem?
Das Problem ist, es gab mal das "kicker" plugin. Somit konnte man aktuelle Ergebnisse etc. abrufen.
Wenn man da auf eine Seite ging dauerte es nicht lang und die wurde geladen.
Wenn ich jetzt mein Plugin öffne, dauert es knapp 7 Sekunden, bis die Seite geladen hat. Und das auf einer 1,6GHZ schnellen Box.
Es gibt aber auch Boxen mit 750 MHZ...
Deswegen frage ich nach einer schnelleren alternative.
Wenn man da auf eine Seite ging dauerte es nicht lang und die wurde geladen.
Wenn ich jetzt mein Plugin öffne, dauert es knapp 7 Sekunden, bis die Seite geladen hat. Und das auf einer 1,6GHZ schnellen Box.
Es gibt aber auch Boxen mit 750 MHZ...
Deswegen frage ich nach einer schnelleren alternative.
- __blackjack__
- User
- Beiträge: 13004
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@egon11: Das ist erst einmal keine Frage von `lxml` *oder*` BeautifulSoup, denn letzteres würde ich auf jeden Fall verwenden, und das kann `lxml` als Parser verwenden. Bei Python 2 würde ich auch dringend vom 'html.parser' aus der Standardbibliothek abraten, denn das war bei Python 2 nur bei fehlerfreiem HTML wirklich verwendbar. Das Modul ist erst in Python 3 robuster geworden.
Bevor Du irgendetwas optimierst solltest Du erst einmal schauen *wo* die Zeit verbraucht wird. Es gibt ja mindestens die drei Teilbereiche laden der Daten über das Netz, parsen des HTML, und dann das suchen und extrahieren der Werte.
Bevor Du irgendetwas optimierst solltest Du erst einmal schauen *wo* die Zeit verbraucht wird. Es gibt ja mindestens die drei Teilbereiche laden der Daten über das Netz, parsen des HTML, und dann das suchen und extrahieren der Werte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis