Seite 5 von 5

Re: Html Seite einlesen

Verfasst: Sonntag 12. Januar 2020, 19:13
von egon11
Habe es jetzt abgeändert. trotzdem noch sehr unzufrieden.

Code: Alles auswählen

def begegnung():
    url = "https://sport.sky.de/bundesliga-spielplan-ergebnisse"
    response = requests.get(url)
    html = BeautifulSoup(response.text, 'lxml')
    liste  = []
    for spiel in html.find_all(class_="sdc-site-fixres__match"):
        print(spiel.text)
        for heimteam in spiel.find_all(class_="sdc-site-fixres__match-cell--hometeam"):
            print(heimteam.text)
        for team in heimteam.find_all(class_="sdc-site-fixres__match-cell--score"):
            print(team.text)

Re: Html Seite einlesen

Verfasst: Sonntag 12. Januar 2020, 19:28
von Sirius3
Wenn ›unzufrieden‹ bedeutet, dass es Quatsch ist, einen Score `team` zu nennen und den auch noch im `heimteam`-Zweig zu suchen, dann hast Du recht.
Eine for-Schleife, wenn es exakt ein Element gibt, ist auch ein Fehler.

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 11:47
von egon11
OK, ich werde es ändern. Mir fehlt jetzt noch das löschen von bestimmten tags, wie kann ich z.b. eine Klasse löschen?
Ich habe mir clear angeschaut. Aber so richtig nicht schlau geworden.
Ich möchte das "data-label-abandoned="X">0</span>" im Text entfernen.

Code: Alles auswählen

<div class="sdc-site-fixres__score"><span class="sdc-site-fixres__score-side sdc-site-fixres__score-side--home" data-update="score-home" data-label-postponed="X" data-label-cancelled="X" data-label-abandoned="X">0</span><span class="sdc-site-fixres__score-ko" data-update="start-time">20:30</span><span class="sdc-site-fixres__score-side sdc-site-fixres__score-side--away" data-update="score-away" data-label-postponed="X" data-label-cancelled="X" data-label-abandoned="X">0</span>

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 11:59
von Sirius3
@egon11: nein, das willst Du nicht. Statt dessen willst Du die Unterstruktur auch noch lesen und in eine passendes Datenstruktur packen.

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 13:46
von egon11
Jetzt habe ich die Spielpaarungen so wie ich es haben möchte, was mir noch fehlt sind die Tages Ansetzungen "<h4 class="sdc-site-fixres__header2">Freitag, 17. Januar</h4>".

Hat jemand eine Idee wie ich die Tages Ansetzungen an der richtigen Stelle mit einfügen kann?

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import re
import itertools
def begegnung():
    url = "https://sport.sky.de/bundesliga-spielplan-ergebnisse"
    response = requests.get(url)
    html = BeautifulSoup(response.text, 'lxml')


    erst = html.find(class_="sdc-site-fixres-box")
    game_list = ([(hometeam.text.encode('utf8', 'replace').replace("ö", "oe").replace("ü", "ue").replace("ä", "ae").replace("ß", "ss").replace("\n", ""), \
            heading.text.encode('utf8', 'replace').replace("ö", "oe").replace("ü", "ue").replace("ä", "ae").replace("ß", "ss").replace("\n", ""),\
           awayteam.text.encode('utf8', 'replace').replace("ö", "oe").replace("ü", "ue").replace("ä", "ae").replace("ß", "ss").replace("\n", "") ) for hometeam,heading,awayteam in \
          itertools.izip_longest(erst.find_all(class_="sdc-site-fixres__match-cell--hometeam"),erst.find_all(class_="sdc-site-fixres__score-ko"),erst.find_all\
                (class_="sdc-site-fixres__match-cell sdc-site-fixres__match-cell--awayteam"))])
    for show in game_list:
        print(show)



if __name__=='__main__':
    begegnung()

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 13:59
von Sirius3
Also, nochmal von vorne: nein. Jedes Spiel ist in einem Element mit Klasse sdc-site-fixres__match. Von dort aus kann man die Unterstruktur parsen. Was man nicht macht, ist die Unterstruktur als eigenständige Listen zusammenzusuchen. Das war doch schonmal richtiger.

Wo hast Du ein Problem, den header zusammen mit den match`s auch noch zu suchen, innerhalb von sdc-site-fixres-box?

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 14:04
von egon11
Sirius3 hat geschrieben: Montag 13. Januar 2020, 13:59 Wo hast Du ein Problem, den header zusammen mit den match`s auch noch zu suchen, innerhalb von sdc-site-fixres-box?
Ja genau. Ich habe schon Stunden versucht, das ganze zu Parsen, mit "for" und was weiß ich.
Letztendlich bekam ich es nicht hin.
Ziel sollte sein Die Tages Ansetzung, dann die jeweiligen Spiel(e), dann wieder Tages Ansetzung u.s.w.

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 18:48
von egon11
Hat keiner ein Schema für mich? Ich komme absolut nicht weiter wie der "Suchbaum" aussehen muss.
Ich wäre dankbar.

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 19:08
von Sirius3

Code: Alles auswählen

date = None
table = []
box = html.find(class_="sdc-site-fixres-box")
for row in box.find_all(class_=['sdc-site-fixres__match','sdc-site-fixres__header2']):
    if 'sdc-site-fixres__header2' in row.attrs['class']:
        date = row.text
    else:
        table.append(dict(
            hometeam=row.find(class_='sdc-site-fixres__match-cell--hometeam').text.strip(),
            awayteam=row.find(class_='sdc-site-fixres__match-cell--awayteam').text.strip(),
            score_home=row.find(class_='sdc-site-fixres__score-side--home').text.strip(),
            score_away=row.find(class_='sdc-site-fixres__score-side--away').text.strip(),
            date=date
        ))

Re: Html Seite einlesen

Verfasst: Montag 13. Januar 2020, 20:26
von egon11
Vielen dank für die große Hilfe, jetzt kann ich damit weiter arbeiten.

Re: Html Seite einlesen

Verfasst: Mittwoch 29. Januar 2020, 15:50
von egon11
Dank eurer Hilfe konnte ich mich weiter in die Sache einarbeiten was html betrifft.
Ich habe hier mal ein funktionierendes Script.
Mich interessiert es, ob ihr Fachleute den Code für ok haltet oder ob man da noch etwas verbessern könnte.
Aber wie gesagt, so wie es ist funktioniert es (Python2).

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup

def work():
    wahr = False
    url = "https://www.kicker.de/1-bundesliga/torjaeger"
    response = requests.get(url)
    html = BeautifulSoup(response.text, 'lxml')
    tabelle = html.find("table")  #tabellenkörper wird gesucht
    liste = []
    liste_end = []

    for end_score in tabelle.find_all("tr"):
        liste.append([table.text.strip().encode('utf8', 'replace').replace("ö", "oe").replace("ü", "ue").replace("ä", "ae").replace("ß", "ss") for table in end_score.find_all("td")])
    liste_end.append("\n {0:<2}   {1:<30}  {2:>6}    {3:>4}".format("Pl", "Spieler", "Spiele", "Tore"))
    for meineliste in liste:
        if len(meineliste) != 0:
            liste_end.append("\n {0:<2}   {1:<30}  {2:>6}    {3:>4}".format(meineliste[0],meineliste[1],meineliste[2],meineliste[6]))

    print("".join(liste_end))

if __name__ == '__main__':
    work()


Re: Html Seite einlesen

Verfasst: Mittwoch 29. Januar 2020, 16:14
von __blackjack__
@egon11: Die `replace()`-Aufrufe von Sonderzeichen *nach* dem kodieren als Bytestrings ist falsch.

Grunddatentypen haben in Namen nichts zu suchen. `liste` und `liste_end` verraten dem Leser ja auch überhaupt gar nicht was da enthalten ist, also was für eine Bedeutung die Werte haben. Man braucht auch nicht wirklich beide wenn man die Elemente die man am Ende nicht haben möchte gar nicht erst zu `liste` hinzufügt.

`end_score` passt IMHO nicht wirklich als Name für eine HTML-Tabellenzeile und `meineliste` ist wieder ein superschlechter generischer Name. `table` ist ebenfalls falsch und sehr irreführend weil es sich gar nicht um eine Tabelle handelt sondern um eine einzelne Zelle in einer Zeile einer Tabelle.

Die Vormatvorlage steht zweimal im Quelltext. Daten und Code sollte man aber nicht wiederholen. Das wäre ein Kandidat für eine Konstante.

Zeilen*ende*zeichen gehören ans *Ende* und nicht an den Anfang. In diesem Fall aber IMHO gar nicht in die Vorlage(n) sondern als Zeichenkette an der die Listenelemente dann verbunden werden.

Sich einfach die erste <table> zu greifen ist für meinen Geschmack nicht robust genug. Ich würde schauen ob man sich da nicht noch an IDs und/oder CSS-Klassen orientieren kann.

Re: Html Seite einlesen

Verfasst: Mittwoch 29. Januar 2020, 16:35
von egon11
@__blackjack__ danke.
Wie würdest du das lösen:
__blackjack__ hat geschrieben: Mittwoch 29. Januar 2020, 16:14 Die `replace()`-Aufrufe von Sonderzeichen *nach* dem kodieren als Bytestrings ist falsch.

Man braucht auch nicht wirklich beide wenn man die Elemente die man am Ende nicht haben möchte gar nicht erst zu `liste` hinzufügt.
Und was meinst du mit "Vormatvorlage steht zweimal im Quelltext".

Re: Html Seite einlesen

Verfasst: Mittwoch 29. Januar 2020, 17:26
von Sirius3
Diese Formatvorlage: "\n {0:<2} {1:<30} {2:>6} {3:>4}"

Du encodierst den Text in UTF8, so dass "ö" zu zwei Bytes wird und diese zwei Bytes ersetzt Du dann durch "oe". UTF8 ist da zum Glück ein gutmütiges Encoding, aber generell sollte man das Encodieren erst dann machen, wenn man etwas ausgeben will, und die Datenverarbeitung komplett in Unicode machen.

Bei einer Zeile wie `wahr = False` kringeln sich mir die Zehennägel. url sollte als Konstante am Anfang der Datei stehen. Und wenn Du `meineliste` schreibst, wo ist dann `unsereliste`?

Re: Html Seite einlesen

Verfasst: Mittwoch 29. Januar 2020, 17:34
von egon11
Also soll ich zuerst ö durch oe ersetzen und dann später erst in UTF8 encoden?

Den Rest habe ich verstanden.
'wahr = False' ist wirklich bisschen lustig. Habe es abgeändert :D

Re: Html Seite einlesen

Verfasst: Donnerstag 30. Januar 2020, 09:12
von egon11
Ich habe jetzt eine variable erstellt, welche ich immer aufrufe:

Code: Alles auswählen

my_line = "\n" + " {0:<2}   {1:<30}  {2:>6}    {3:>4}"
dann aufrufen mit:

Code: Alles auswählen

my_line.format(....
Ist das jetzt so ok?

Re: Html Seite einlesen

Verfasst: Donnerstag 30. Januar 2020, 10:39
von Sirius3
Auch hier gilt wieder, das my_-Präfix bietet keinen Mehrwert und line ist keine Name für ein FORMAT_TEMPLATE

Re: Html Seite einlesen

Verfasst: Donnerstag 30. Januar 2020, 11:38
von __blackjack__
Warum da zwei Zeichenkettenliterale per ``+`` zusammengesetzt werden ist mir auch nicht so ganz klar. Zudem denke ich immer noch das Zeilenendezeichen ans Zeilenende gehören. Sonst hiessen sie ja Zeilenanfangszeichen. 😉