Html Seite einlesen

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.
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ich möchte eine Webseite LESBAR in python einlesen lassen.
Beispielseite ist Kicker mit Tabelle.
Das folgende Beispiel kommt sehr nah an meine Vorstellungen, nur ich kann sie noch nicht richtig bearbeiten, ich möchte mit split etc etwas weglöschen u.s.w.

Code: Alles auswählen

import requests as req
from bs4 import BeautifulSoup
import csv
import pandas as pd

url = "https://www.kicker.de/1-bundesliga/tabelle"


reg = req.get(url)
soup = BeautifulSoup(reg.content, 'html.parser')
sou = soup.find_all('table')[0]
end = pd.read_html(str(sou))[0]

print(end)
Welche Möglichkeiten habe ich noch um es beliebig umwandeln zu können?
Benutzeravatar
sparrow
User
Beiträge: 4522
Registriert: Freitag 17. April 2009, 10:28

Bitte benutze sprechende Variablen. "req" ist schon schwierg. "sou" absolut unpassend. Das ist ein bisschen wie die Wanze auf der Mauer, die hinten immer einen Buchstaben verliert.

Wenn du schon ein Schwergewicht wie Pandas für so eine Aufgabe auffährst, musst du dich damit auch beschäftigen. "end" ist in diesem Fall ein Objekt vom Typ Dataframe, entsprechend musst du auf den Inhalt zugreifen. Mit "print" bekommst du ja nur eine für das Auge aufgehübschte Ausgabe.
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Oder geht es noch einfacher ohne Pandas?
Benutzeravatar
sparrow
User
Beiträge: 4522
Registriert: Freitag 17. April 2009, 10:28

Es ist ja schon "einfach". Du bekomst mit 3 Zeilen Code die gewünschten Daten in einem Dataframe.
Bisher hast du noch nicht verraten, wie du die Daten weiterverarbeiten möchtest.
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ich möchte die Daten, also das Datenframe Zeilenweise einlesen und ab .bzw. nur die gewünschte Position ausgeben.
Sirius3
User
Beiträge: 18245
Registriert: Sonntag 21. Oktober 2012, 17:20

@egon11: die Fragestellung reicht nicht aus, um Dir helfen zu können. Du weinst also irgendwas mit den Daten machen? Dann mach das doch.
Was willst du konkret tun? Was hast du versucht? Was funktioniert dabei nicht?
Hast du das pandas-Tutorial schon durchgearbeitet?
Ist Pandas dafür überhaupt notwendig, oder reicht nicht beaurifulsoup dafür aus? Und wenn Pandas gebraucht wird, warum der Umweg über beautifulsoup?
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ziel ist, ich möchte eine Webseite so angezeigt bekommen, bzw in eine Datei geschrieben werden, wie sie auf der Webseite zu sehen ist.

Hab mir mal jetzt "BeautifulSoup" näher angeschaut.
Bin bis jetzt zu diesen Ergebnis gekommen.

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup

url = "https://www.kicker.de/1-bundesliga/tabelle"
response = requests.get(url)
parsen = BeautifulSoup(response.content, 'html.parser')
content_type = response.headers['Content-Type'].lower()

for index, i in enumerate(parsen.select('li')):
    print(i.text)
Leider ist das noch sehr wenig, damit kann man nichts anfangen.
Frage: kann man das überhaupt "BeautifulSoup" realisieren?
Benutzeravatar
snafu
User
Beiträge: 6844
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

egon11 hat geschrieben: Dienstag 24. Dezember 2019, 09:57 Ziel ist, ich möchte eine Webseite so angezeigt bekommen, bzw in eine Datei geschrieben werden, wie sie auf der Webseite zu sehen ist.
Du meinst, dass die Seite wie im Browser gerendert wird, nur innerhalb deiner grafischen Programmoberfläche?

Oder willst du die Tabelle mit ASCII-Zeichen "rendern" lassen?

Und nimmt als Beispiel besser die vom 13. Spieltag. Da ist die Reihenfolge schöner. :)
Sirius3
User
Beiträge: 18245
Registriert: Sonntag 21. Oktober 2012, 17:20

@egon11: ich dachte, Du wolltest die Tabelle auslesen, nicht die <li>-Elemente?

Was bedeutet „wie sie auf der Wbseite zu sehen ist”?
Wenn Du eine Tabelle als Text-Datei haben willst, geht das einfach:

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup

url = "https://www.kicker.de/1-bundesliga/tabelle"
response = requests.get(url)
tabelle = pd.read_html(response.content, header=0)[0]
tabelle.to_csv('tabelle.csv')
Mit BeautifulSoup geht das natürlich genauso, ist nur mehr Aufwand:

Code: Alles auswählen

html = BeautifulSoup(response.content, 'html.parser')
tabelle = html.find('table')
for row in tabelle.find_all('tr'):
    print([cell.text.strip() for cell in row.find_all('td')]
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Vielen dank und an alle frohe Weihnachten.

Jetzt steige ich ein bisschen durch, ist genau das was ich brauche.
Daher, das ich mich mit html Texten leider nicht auskenne, wusste ich nicht dass vor jeden "brauchbaren" Text "tr" und "td" steht, ist das immer so?
Ich frage nur für die Zukunft, kann man daran immer erkennen welchen Text ich extrahieren muss?

Und das Modul 'BeautifulSoup' ist ja auch richtig mächtig.
nezzcarth
User
Beiträge: 1739
Registriert: Samstag 16. April 2011, 12:47

egon11 hat geschrieben: Mittwoch 25. Dezember 2019, 08:38 Daher, das ich mich mit html Texten leider nicht auskenne, wusste ich nicht dass vor jeden "brauchbaren" Text "tr" und "td" steht, ist das immer so?
Ich frage nur für die Zukunft, kann man daran immer erkennen welchen Text ich extrahieren muss?
Das ist nur bei Tabellen so, ansonsten nicht. tr steht für "table row" -- zeichnet also Zeilen in Tabellen aus -- und td ("table data") markiert einzelne Zellen. Es muss auch nicht unbedingt Text darin stehen. In beliebigen HTML Dokumenten kann der gesuchte Text in diversen Elementen stecken. Wenn man Informationen aus HTML auslesen möchte, kommt man kaum darum herum, es einigermaßen zu lernen.
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Also wird z.b. alles was "td" rausgefiltert und nur der Text extrahiert?
Wenn ich jetzt einen anderen Text habe, greift dann immer noch das "trd"?

Edit: habe gerade gemerkt, dass auf einer anderen Webseite das wieder anders ist, da wird z.b. der Namen der Mannschaft 3x heraus geschrieben.
Ich werde es mir mal genauer anschauen was da zu machen ist.
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ich habe mal noch eine Frage, kann man mit den Modul "beautifulsoup" auch Zeilen nicht ausgeben lassen die mit "find_all" gefunden werden?
Ich möchte bei der Ausgabe:

Code: Alles auswählen

<td class="kick__table--ranking__teamname kick__table--ranking__index kick__t__a__l kick__respt-m-o-4 kick__respt-m-w-120 kick__t__a__l">
<a href="/sc-paderborn-07-109/info/1-bundesliga/2019-20">
<span class="kick__table--show-mobile">Paderborn (N)</span>
<span class="kick__table--show-desktop">SC Paderborn 07 (N)</span>
Die Zeile

Code: Alles auswählen

<span class="kick__table--show-mobile">Paderborn (N)</span>
weg haben, weil da sonst immer der Vereinsname doppelt angezeigt wird.
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@egon11: Das Element das Du nicht haben möchtest hat ja eine eindeutige, sogar semantisch sinnvoll benannte CSS-Klasse. Daran kannst Du es identifizieren und entfernen.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

OK, und wie macht man das?
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@egon11: Das steht in der Dokumentation. Da gibt es ein Kapitel zum Suchen („Searching the tree“) wo es auch einen Abschnitt zum suchen nach CSS-Klassen gibt, und ein Kapitel zum Verändern des Dokumen-Baums („Modifying the tree“) wo unter anderem eine Methode zum entfernen und zerstören von Elementen/Unterbäumen beschrieben wird.

Wobei das aber auch nur Sinn macht wenn man den Dokumentbaum auch wieder als HTML speichern möchte. Wenn es darum geht Informationen aus dem Baum zu holen, dann holt man sich eben nur die Informationen heraus die man haben will und ignoriert alles was man nicht haben will. In diesem Fall würde man sich also nur den Vereinsnamen nehmen den man haben will. Der hat ja ebenfalls eine (sogar semantisch sinnvoll benannte) CSS-Klasse.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ich komme einfach nicht weiter, ich möchte alles heraus "löschen" was mit der Klasse "kick__table--show-mobile" zu tun hat, leider bekomme ich gar nichts angezeigt, ich werde mit der html noch verrückt :roll:

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup
import re
import time

url = "https://www.kicker.de/1-bundesliga/tabelle"
response = requests.get(url)
html = BeautifulSoup(response.content, 'html.parser')
tabelle = html.find('table')
liste = []

no_class = tabelle.find_all(class_="kick__table--show-mobile")
for i in tabelle.find_all('tr'):
    if not no_class:
        print(i)

Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@egon11: Das macht doch so überhaupt gar keinen Sinn. Der Wert von `no_class` ändert sich in der Schleife nicht, also wird das ``if`` dort entweder immer zutreffen oder nie zutreffen, also wäre es effizienter das vor die Schleife zu ziehen. Da ja aber wohl auf jeden Fall Elemente mit dieser Klasse vorkommen werden, kann man sich das ``if`` auch gleich ganz sparen, denn dann ist die Bedingung ja *nie* wahr.

`i` ist ein schlechter Name für alles was keine ganze Zahl ist. An dem Namen kann keiner erkennen das es sich um ein `Tag`-Objekt handelt das eine HTML-Tabellenzeile repräsentiert.

Ich bin mir auch immer nichts sicher... Nein, ich bin mir sicher das Du nichts löschen möchtest, warum auch. Was machst Du denn mit dem Dokumentbaum danach? Ich dachte Du willst daraus Daten extrahieren und die Anzeigen. Dazu verändert man ja nicht den Dokumentbaum, sondern zieht sich die Daten heraus, die man haben will. Das ist der erste Schritt. Danach kann man die dann so aufbereiten wie man sie gerne haben möchte. Und selbst wenn das wieder HTML sein sollte, ist das IMHO ein separater Schritt der nichts mehr mit dem `BeautifulSoup`-Objekt und den `Tag`-Objekten zu tun hat.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
egon11
User
Beiträge: 363
Registriert: Mittwoch 14. Dezember 2016, 20:59

Ja ich möchte die Daten extrahieren und anzeigen. Mit löschen meinte ich, aus dem ausgegeben text "for i in tabelle.find_all('tr'):..."
die Zeilen noch heraus löschen.
Beispiel:
Ich möchte genau das gegenteil von

Code: Alles auswählen

tabelle.find_all(class_='kick__table--show-mobile'))
Also es soll es NICHT ausgeben.
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@egon11: Ja aber warum? Das scheint mir nicht zielführend zu sein.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten