Seite 1 von 1

webcrawler = "td class="number" headers=" auslesen

Verfasst: Sonntag 17. Oktober 2021, 08:59
von alfer
Hallo,

Ich bin dabei mir einen Webcrawler zu bauen der Aktiendaten von Morningstar zieht und diese in eine csv Datei speichert. Soweit läuft es ganz gut, allerdings hänge ich an folgenden Problem:

Mit diesem Code lese ich eine Reihe von daten aus einer Tabelle (Ertrag):

Code: Alles auswählen

url = "https://tools.morningstar.de/de/stockreport/default.aspx?tab=10&vw=is&SecurityToken=0P0001DHJ2%5D3%5D0%5DE0WWE%24%24ALL&Id=0P0001DHJ2&ClientFund=0&CurrencyId=EUR"
seite = requests.get(url)
    
bs4_seite = None
if seite.status_code == 200:
    bs4_seite = bs4.BeautifulSoup(seite.content, 'html.parser')
else:
    print('Seite konnte nicht geladen werden.', url)
    
table_incomestatement = bs4_seite.find('div', {'id': 'FinancialsIncomeStatement'})
table_tbody = table_incomestatement.find('tbody')
table_tr = table_tbody.find('tr')
    
for stockreport in table_tr.select("td"):
    print(stockreport)
Es werde auch alle 5 Einträge wieder gegeben:

Code: Alles auswählen

<td class="number" headers="MsStockReportFisY1">659,36</td>
<td class="number" headers="MsStockReportFisY2">1.012,44</td>
<td class="number" headers="MsStockReportFisY3">1.652,95</td>
<td class="number" headers="MsStockReportFisY4">2.656,77</td>
<td class="number" headers="MsStockReportFisY5">3.641,39</td>
Allerdings will ich jedem Eintrag in eine variable packen, also y1, y2, y3 usw. Nach vielen Googlen und YouTube schauen, gelingt es mir leider immer noch nicht.

Wäre super, wenn mir jemand helfen könnte.

Re: webcrawler = "td class="number" headers=" auslesen

Verfasst: Sonntag 17. Oktober 2021, 10:22
von Sirius3
Deine Fehlerbehandlung ist fehlerhaft. Wenn status_code nicht 200 ist, ist bs4_seite None und hat keine Methode find, so dass das Programm mit einem Fehler abbricht, der an einer Stelle auftritt, wo das ursprüngliche Problem gar nicht mehr sichtbar ist.

Statt einzelner Variablen benutzt man eine passende Datenstruktur: Liste, Wörterbuch oder was auch immmer für die Weiterverrbeitung nötig ist.
Wie sehen die Daten genau aus, die Du brauchst? Nur die Zahlen, die Headers? Wie viele Zeilen gibt es?

Re: webcrawler = "td class="number" headers=" auslesen

Verfasst: Sonntag 17. Oktober 2021, 11:11
von alfer
Danke für die schnelle Antwort!
Sirius3 hat geschrieben: Sonntag 17. Oktober 2021, 10:22 Deine Fehlerbehandlung ist fehlerhaft. Wenn status_code nicht 200 ist, ist bs4_seite None und hat keine Methode find, so dass das Programm mit einem Fehler abbricht, der an einer Stelle auftritt, wo das ursprüngliche Problem gar nicht mehr sichtbar ist.
Ist das ein generelles Problem oder bezieht sich das direkt auf die daten des weiteren codes? Das Program läuft bei mir generell durch, von daher habe ich nicht so darauf geachtet.
Sirius3 hat geschrieben: Sonntag 17. Oktober 2021, 10:22Statt einzelner Variablen benutzt man eine passende Datenstruktur: Liste, Wörterbuch oder was auch immmer für die Weiterverrbeitung nötig ist.
Wie sehen die Daten genau aus, die Du brauchst? Nur die Zahlen, die Headers? Wie viele Zeilen gibt es?
Es geht um die Zahlen. Wenn ich

Code: Alles auswählen

print(stockreport.text)
benutze werden auch nur diese wiedergegeben.

Es sind immer fünf datensätze, wenn kein Eintrag vorhanden ist, wird ein - benutzt. Die daten will ich in ein Dictionarie packen und das dann in ein csv datei schreiben (kommt später noch).

Re: webcrawler = "td class="number" headers=" auslesen

Verfasst: Dienstag 19. Oktober 2021, 10:32
von rogerb
@alfer,

der Rückgabewert eines HTTP Requests wird im allgemeinen Response genannt und der Rückgabewert des bs4 html.parsers ist ein "soup" Objekt.
Wenn man sich an solche Namenskonventionen hält, macht es den Code für andere auch verständlicher.
Du kannst einfach das csv-paket von Python verwenden um die Daten zu schreiben:

Code: Alles auswählen

import requests
import bs4
import csv

url = "https://tools.morningstar.de/de/stockreport/default.aspx?tab=10&vw=is&SecurityToken=0P0001DHJ2%5D3%5D0%5DE0WWE%24%24ALL&Id=0P0001DHJ2&ClientFund=0&CurrencyId=EUR"
response = requests.get(url)

if response.status_code == 200:
    soup = bs4.BeautifulSoup(response.content, "html.parser")
else:
    print("Seite konnte nicht geladen werden.", url)

table_incomestatement = soup.find("div", {"id": "FinancialsIncomeStatement"})
table_tbody = table_incomestatement.find("tbody")
table_tr = table_tbody.find("tr")


with open("data.csv", "w", encoding="utf-8", newline="") as csv_file:
    writer = csv.writer(csv_file, delimiter=";")
    writer.writerow((stockreport.text for stockreport in table_tr.select("td")))
Leider enthalten die Eurobeträge Komma als Dezimalzeichen. Daher muss man die gegebenen Falls in "float" umwandeln und dann mit dem Dezimalpunkt speichern. Oder man nimmt als Trennzeichen in der CSV-Datei ein Semikolon.

Re: webcrawler = "td class="number" headers=" auslesen

Verfasst: Dienstag 19. Oktober 2021, 11:37
von pillmuncher
@rogerb: Für Geldbeträge sollte man Decimals verwenden, nicht floats.

Re: webcrawler = "td class="number" headers=" auslesen

Verfasst: Dienstag 19. Oktober 2021, 12:04
von alfer
rogerb hat geschrieben: Dienstag 19. Oktober 2021, 10:32 @alfer,

der Rückgabewert eines HTTP Requests wird im allgemeinen Response genannt und der Rückgabewert des bs4 html.parsers ist ein "soup" Objekt.
Wenn man sich an solche Namenskonventionen hält, macht es den Code für andere auch verständlicher.
Du kannst einfach das csv-paket von Python verwenden um die Daten zu schreiben:

Code: Alles auswählen

import requests
import bs4
import csv

url = "https://tools.morningstar.de/de/stockreport/default.aspx?tab=10&vw=is&SecurityToken=0P0001DHJ2%5D3%5D0%5DE0WWE%24%24ALL&Id=0P0001DHJ2&ClientFund=0&CurrencyId=EUR"
response = requests.get(url)

if response.status_code == 200:
    soup = bs4.BeautifulSoup(response.content, "html.parser")
else:
    print("Seite konnte nicht geladen werden.", url)

table_incomestatement = soup.find("div", {"id": "FinancialsIncomeStatement"})
table_tbody = table_incomestatement.find("tbody")
table_tr = table_tbody.find("tr")


with open("data.csv", "w", encoding="utf-8", newline="") as csv_file:
    writer = csv.writer(csv_file, delimiter=";")
    writer.writerow((stockreport.text for stockreport in table_tr.select("td")))
Leider enthalten die Eurobeträge Komma als Dezimalzeichen. Daher muss man die gegebenen Falls in "float" umwandeln und dann mit dem Dezimalpunkt speichern. Oder man nimmt als Trennzeichen in der CSV-Datei ein Semikolon.
Hat mir sehr geholfen! Vielen dank!!!

Semikolon ist kein Problem, bei meiner NL office Version ist das die standaart Einstellung!