@Assassin4711: Bei Zeichenkettenliteralen mit Backslashes sollte man entweder alle escapen oder ein ”rohes” Zeichenkettenliteral verwenden.
Den Backslash um logische Zeilen fortzuführen braucht man nur sehr selten. Solange es noch ausstehende schliessende Klammern gibt, wie bei dem `print()`-Aufruf, weiss der Compiler auch so, dass die logische Zeile noch nicht zuende sein kann.
Statt die Zeilen in zwei Schritten über ID und Tag-Namen zu ermitteln, könnte man das auch in *einen* CSS-Selektor stecken.
Statt ``not a in b`` würde man eher ``a not in b`` schreiben. Ersteres sind zwei Operatoren, letzteres nur ein Operator. Jup ``not in`` ist *ein* Operator der aus zwei Schlüsselwörtern besteht.
Aber die Bedingung braucht man nicht, denn da wird ja nur das Gegenteil von dem ``if`` davor geprüft, und dazu braucht man keine explizite Prüfung, da kann man einfach ``else`` verwenden.
Die nummerierten `data_field*`-Präfixe sollten nicht sein.
Ist das ``.replace("\n", "")`` vor jedem ``.strip()`` tatsächlich notwendig/sinnvoll? `strip()` entfernt auch Zeilenendezeichen an beiden Enden. Das `replace()` bringt also nur etwas wenn auch Zeilenendezeichen innerhalb der Zeichenkette vorkommen. Dann ist aber das ersetzen durch eine leere Zeichenkette eventuell keine gute Idee, sondern man möchte da vielleicht eher ein Leerzeichen haben, weil sonst das Ende von der ersten Zeile *direkt* an den Anfang der nächsten Zeile angefügt wird. Aber auf den ersten Blick sehen die Daten nicht aus, als wären da mehrzeilige Texte‽ Auch im Code sieht das eher so aus als wenn das einfach Cargo-Cult-mässig einfach an jeden Zugriff auf `text`-Attribute drangehängt ist, denn um zu prüfen ob ein Doppelpunkt in einem Text enthalten ist, braucht man weder Zeilenendezeichen entfernen, noch Whitespace an den beiden Enden.
Bei dem Test auf ":" ist auch wieder unnötigerweise ein ``elif`` mit genau der gegensätzlichen Bedingung statt einfach einem ``else``.
Die beiden Zweige machen auch nahezu das gleiche, die unterscheiden sich nur durch den Versatz welche beiden Tabellenzellen verwendet werden.
Ich würde den Code so schreiben, dass er nicht in einen `NameError` läuft, wenn nicht zuerst ein Spielort in der Tabelle erkannt wurde.
Zusammenstückeln von Zeichenketten und Werten mit ``+`` ist eher BASIC als Python. In diesem Fall soll die gleiche Zeichenkette zwischen Werte gesetzt werden. Dafür gibt's die `join()`-Methode auf Zeichenketten. Falls das am Ende in einer CSV-Datei landen soll, würde sich das `csv`-Modul aus der Standardbibliothek anbieten. Das kann nämlich auch mit so Sachen wie Trennzeichen *innerhalb* von Zellen korrekt umgehen.
Code: Alles auswählen
#!/usr/bin/env python3
from selenium import webdriver
CHROME_DRIVER = R"C:\webdrivers\Chromedriver.exe"
def iter_stripped_texts(elements, start_index=None, end_index=None):
return (
element.text.strip()
for element in elements[slice(start_index, end_index)]
)
def main():
driver = webdriver.Chrome(CHROME_DRIVER)
driver.get("https://www.oddsportal.com/matches/tennis/")
country = tournament = None
for row in driver.find_elements_by_css_selector("#table-matches tr"):
if "dark" in row.get_attribute("class"):
# dark: alle Zeilen die den Autragungsort enthalten
country, tournament = iter_stripped_texts(
row.find_elements_by_tag_name("a")
)
else:
if country is None:
raise ValueError(
"expected row with country and tournament first."
)
cells = row.find_elements_by_tag_name("td")
time, player = iter_stripped_texts(cells, 0, 2)
offset = 3 if ":" in cells[2].text else 2
home_odd, away_odd = iter_stripped_texts(cells, offset, offset + 2)
print(
";".join(
[country, tournament, time, player, home_odd, away_odd]
)
)
if __name__ == "__main__":
main()