Pelikan666
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Hallo Community, um unnötige Zeitverschwendung während des Studiums, durch einen Minijob, zu vermeiden, habe ich mich dem Sportwetten gewidmet - mit Erfolg. Ich arbeite derzeit nur mit Libre Calc., habe dort 1680 Variablen und 14 Team.
Nun Frage ich mich, ob die Möglichkeit bestünde, ein Programm zu schreiben, hierbei spielt die Sprache keine Rolle, das die Daten immer nach jedem Spieltag aktualisiert. In wie weit ließe sich meine Vorstellung umsetzten und wo könnten Probleme auftreten ? LG
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Pelikan666 schrieb: In wie weit ließe sich meine Vorstellung umsetzten und wo könnten Probleme auftreten ?
Deine Beschreibung ist zu vage gehalten, um da was Konkretes schreiben zu können. Wenn es in einer Tabellenkalkulation läuft, klappt das grundsätzlich auch in so gut wie jeder anderen Sprache... Du musst dir halt klar machen, woher die Daten kommen und wie du sie automatisiert für das gewünschte Zielformat aufbereiten lassen kannst. Diesen Teil, bei dem man erst mal einen grundlegenden Programmablauf entwirft, kann man unabhängig von einer Programmiersprache lösen. Und dann kommt der Teil, der dich vermutlich (zumindest für ein paar Wochen) vermutlich deutlich mehr Zeit als ein Minijob kosten wird: du musst dir eine Programmiersprache aussuchen, mit der du die einzelnen Schritte tatsächlich realisieren willst, ihre Syntax und Idiome lernen, dir ggf. sinnvolle Bibliotheken suchen, um möglichst wenig komplett selber umsetzen zu müssen und den Code schreiben, der die nötigen Schritte abarbeiten kann. Probleme und Herausforderungen kann es viele geben:
die eigene Motivation das Projekt durchzuziehen Bugs suchen und beheben man versteht die Feinheiten der gewählten Programmiersprache gerade als Anfänger oft nicht gut genug und wundert sich, warum der Code nicht das tut, was man möchte die Datenquelle ändert ihr Format im Laufe der Zeit und man muss seine Scraper/Parser anpassen historisch gewachsener und schlecht strukturierter Code kann dazu führen, dass das Programm schlecht wartbar bzw. nur mit viel Mühe für zukünftige Erweiterungen anpassbar ist
habe dort 1680 Variablen und 14 Team
Wenn Variablen Team-bezogen sind, kann es sich lohnen, das entsprechend zu Kapseln (man könnte z.B. Objektorientierte_Programmierung nutzen) - und man könnte überlegen, ob man die Auswertung nicht auch gleich außerhalb der Tabellenkalkulation macht.
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Deine Beschreibung ist zu vage gehalten, um da was Konkretes schreiben zu können.
Nehmen wir jetzt mal [bundesliga.at] als Bezugsquelle. Manuell tippe ich jedes Ergebnis, wie Tore, Pässe, Fouls,... von dieser Seite in meine libre calc - Tabelle ein. Ich möchte ein Programm schreiben, dass die Ergebnisse von der Bezugsquelle [bundesliga.at] automatisch in eine Datenbank übernimmt. Heißt, am Ende will ich nur auf den "Update-Button" des Programms drücken, um die neuen Ergebnisse zu erhalten, anstatt immer jedes Ergbeniss einzeln manuell in eine Tabelle einzutragen.
Bestünde die Möglichkeit, ausgewählte Daten, wie wie Tore, Pässe, Fouls,... von [bundesliga.at] zu erfassen und in einem Programm sichtbar zu machen ? Die Bezugsquelle kann natürlich variieren. Mir geht es in erster Linie nur darum, ob das prinzipiell möglich ist.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Machen kann man das sicherlich (die Seite scheint die eigentlichen Daten für die Partien jeweils aus einer JSON-Datei zu beziehen, so dass man sich das lästige Parsen von HTML in Kombination mit JS-Datenquellen sparen kann - das kannst du dir selber mit den in Firefox oder Chrome/Chromium eingebauten Web-Developer Tools ansehen, die man mit F12 aktivieren kann), aber die AGB §2 erlauben die ungefragte kommerziellen Nutzung und Speicherung der Daten nicht.
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Wenn ich das Richtig interpretiert habe, kommen die Daten von einem Service von Amazon. 😳
Die JSON-Datei kann ich auch nicht öffnen, da <body>: <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NLQHQQ" height="0" width="0" style="display:none;visibility:hidden"></iframe>
Wenn ich auf eine Website gehe, lese ich mir immer die AGBs durch, deshalb ist mir bewusst, dass > die ungefragte kommerziellen Nutzung und Speicherung der Daten < unerlaubt ist. Jetzt muss ich wohl nach Alternativen suche, die sich in der Theorie umsetzten ließen. Wäre das Parsen von HTML in Kombination mit JS-Datenquellen eine solche ?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Pelikan666 schrieb: Wenn ich das Richtig interpretiert habe, kommen die Daten von einem Service von Amazon. 😳
Das kann ich so nicht nachvollziehen. Die JSON-Datei kann ich auch nicht öffnen, da <body>: <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NLQHQQ" height="0" width="0" style="display:none;visibility:hidden"></iframe>
Ich weiß ja nicht, was du da gesehen haben willst, aber die Daten für https://www.bundesliga.at/de/spielplan/ stammen u.a. aus https://www.bundesliga.at/fileadmin/json/Spielplaene/Spielplan_BL.json. Mit der ID für die Spiele kann man dann eine Addresse wie https://www.bundesliga.at/fileadmin/json/Spiele/Matchcenter_52099.json für ein bestimmtes Spiel bilden.
Jetzt muss ich wohl nach Alternativen suche, die sich in der Theorie umsetzten ließen. Wäre das Parsen von HTML in Kombination mit JS-Datenquellen eine solche ?
Auf den ersten Blick sieht das für mich so aus, als ob man nur die json-Datei für den jeweiligen Spielplan und die json-Datei für das Match benötigt. HTML zu parsen scheint da erst mal nicht notwendig - mit dynamischem JS ist das auch tricky, da könnte man in Richtung Selenium denken, das kann einen Browser ansteuern, von dem man sich dann den kompletten DOM Tree holen und den parsen kann.
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Anscheinend habe ich was falsch interpretiert. 🦆
Der Spielplan und das Match sind mir vollkommen egal. Folgende Daten sind von Relevanz:
https://www.bundesliga.com/de/statistiken/bundesliga/aktuelle-saison/alle-spieltage/club-statistiken Danke, mit Selenium habe ich nun jetzt ein (hoffentlich) guten Anhaltspunkt.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Pelikan666 schrieb: Nehmen wir jetzt mal [bundesliga.at] als Bezugsquelle.
Pelikan666 schrieb: Anscheinend habe ich was falsch interpretiert. 🦆
Der Spielplan und das Match sind mir vollkommen egal. Folgende Daten sind von Relevanz:
https://www.bundesliga.com/de/statistiken/bundesliga/aktuelle-saison/alle-spieltage/club-statistiken
Du bis da auf einmal von bundesliga.at auf bundesliga.com gewechselt... - die Seite in der Tat einen Service bei Amazon AWS zu nutzen, bei dem die Daten über GET- und OPTION-Requests geholt werden, die durch Daten aus dem Header geschützt sind und sich dadurch nicht so einfach von extern abrufen lassen.
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Ich merk schon, du hast es voll drauf ! Wenn man manuell die Zeilen im Tree kopieren kann, dann müsste das doch auch mit Selenium, unabhängig von der Bezugsquelle, funktionieren ? Ich stell mir das so vor, dass man mithilfe von Selenium die spezifischen Daten erfasst und irgendwie speichert. Das gespeicherte Dokument bindet man dann in eine Datenbank ein. Das ist alles äußerst schwammig formuliert, was meiner Unwissenheit geschuldet ist. Ich bräuchte lediglich ein Grundgerüst wie es funktioniert, der Rest, also die Umsetzung, ist erstmal nebensächlich.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Für die Umsetzung musst du dich dann so langsam für eine Programmiersprache entscheiden, Selenium bietet da einige Möglichkeiten bei der Sprachunterstützung: https://www.seleniumhq.org/docs/03_webdriver.jsp Ich nutze gerne Python3, weil man damit vergleichsweise wenig Zeit und Code benötigt, um Dinge umzusetzen.
Als erstes sollte man sich eine Virtuelle Umgebung aufbauen, in der man die benötigten Module installieren kann (vgl. venv): sudo apt install python3-venv python3-pip jq python-lxml
mkdir -p ~/Projekte/dom_loader
cd ~/Projekte/dom_loader
python3 -m venv .venv
. .venv/bin/activate
pip install -U pip selenium bs4 lxml Damit Firefox durch Selenium gesteuert werden kann, musst du den geckodriver installieren - hier gibt es ein Skript, das das automatisch für dich erledigen kann: https://askubuntu.com/a/928514 Dann ein Grundgerüst, um sich eine Seite zu holen - hier mal am Beispiel für https://www.bundesliga.com/de/statistiken/bundesliga/aktuelle-saison/alle-spieltage/club-statistiken/torschusse:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | #!/usr/bin/env python3
import sys
from datetime import datetime
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
URL = "https://www.bundesliga.com/de/statistiken/bundesliga/aktuelle-saison/alle-spieltage/club-statistiken/torschusse"
caps = DesiredCapabilities().FIREFOX
caps["pageLoadStrategy"] = "normal"
# Create a new instance of the Firefox driver
driver = webdriver.Firefox()
# go to the url
driver.get(URL)
try:
# we have to wait for the page to load, we wait up to 20 seconds until
# we can see that the website title contains "Torschüsse"
WebDriverWait(driver, 20).until(EC.title_contains("Torschüsse"))
except TimeoutException:
print("Site took to long, data might be incomplete", file=sys.stderr)
finally:
# form a filename containing a timestamp
filename = f"Torschüsse_1._BL_{datetime.now()}.html"
# write the html to a file (useful for later debugging)
with open(filename, 'w') as f:
f.write(driver.page_source)
print(f"written data to {filename}")
# close the firefox driver
driver.quit()
|
Statt den Browser direkt wieder zu schließen könnte man natürlich gleich noch andere URLs laden und deren DOM-Tree speichern, um Zeit zu sparen. Ich mache das Parsen der HTML-Daten mit BeautifulSoup4, weil das unabhängig von Selenium funktioniert und man so die Möglichkeit hat bereits heruntergeladene Daten zu verwenden, statt Zeitaufwendig jedes Mal einen Browser starten zu müssen. Das wäre dann ein Skript, das eine HTML-Datei als Argument akzeptiert und eine torschüsse.csv mit den Daten aus der HTML-Datei erzeugt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #!/usr/bin/env python3
import csv
import sys
from bs4 import BeautifulSoup
with open(sys.argv[1]) as f:
page = f.read()
soup = BeautifulSoup(page, "lxml")
with open("torschüsse.csv", 'w', newline='') as csvfile:
csvwriter = csv.writer(csvfile)
for element in soup.find_all('a', class_="list-group-item"):
club = element.find('span', class_="club__club").text.strip()
num_goals = element.find('span', class_="club__score").text.strip()
csvwriter.writerow((club, num_goals))
|
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
Danke für dein nützlichen Tipp. Habe das Programm allerdings etwas anders strukturiert, jetzt kann ich mir alle Daten holen die ich brauche. 👍
|
Pelikan666
(Themenstarter)
Anmeldungsdatum: 22. September 2019
Beiträge: 19
|
@seahawk1986 Wenn ich deinen Code ausführe, kommt:
"with open(sys.argv[1]) as f:
IndexError: list index out of range" Ich möchte deinen Code verstehen, nur ist mir nicht bewusst, wo der Fehler liegen könnte.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Mein Skript erwartet eine HTML-Datei als Argument. In Python ist sys.argv die Liste der Argumente, das Element mit Index 0 ist der Name des Skripts, das mit dem Index 1 das erste dem Skript Argument usw. - in der Dokumentation für Python wird das detailliert beschrieben: https://docs.python.org/3/library/sys.html#sys.argv
|