URL auf Webpage öffnen

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.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

Hi Zusammen,

ich möchte auf der URL: https://www.tennisergebnisse.net/atp/rangliste/ die Einzelnen Spieler der Weltrangliste durchklicken und dann auf der sich öffnenden Seite die Ergebnisse der Spiele rausholen. Die Daten werde ich da schon extrahiert bekommen. Allerdings habe ich keinen Ansatz wie ich den Part mit dem durchklicken der Links / auf der neuen Seite Daten rausholen / und dann wieder zurückspringen hinbekommen.

Hat da jemand einen Ansatz für mich?

Also ich müsste ja eine Schleife bilden die die einzelnen Links öffnet sich merkt welcher Link geöffnet wurde damit die Schleife dann beim nächsten Spieler weiter machen kann ....

Hat da einer von euch eine Idee (gerne einen Code aber auch Quellen sind gut ....

Viele Grüße und DANKE
Dirk
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Such nach Tutorials wie man einen webcrawler baut. Denn das machst du hier effektiv.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Assassin4711: Falls es hier immer noch um Selenium geht: Damit steuert man ja den Browser. Wie kommst Du denn im Browser wieder auf die Seite zurück, auf der Du vor dem letzten Klick warst? Genau das kannst Du auch in Selenium fernsteuern.

Wobei die Seite auf den ersten Blich deutlich weniger dynamsisch aussieht wie Dein letztes Ziel. Hier kann man wahrscheinlich mit `requests` und BeautifulSoup arbeiten.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Assassin4711,

aus der ersten Seite kannst du alle Links die zu den einzelnen Spielern führen aus dem HTML-Code auslesen.
Über die Liste iterierts du dann. Wobei du mit Selenium jedes mal die Seite mit dem entsprechenden Link lädtst.

Dabei ist ein Zurückspringen nicht nötig.
Und bei einer Schleife braucht man sich auch nicht zu merken wo man schon war. Das beinhaltet ja die Funktionsweise einer Schleife.
Du bist auf dem richtigen Weg. Fang doch einfach an und wenn es konkrete Probleme gibt, kannst du ja nochmal fragen.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

Also ich hatte mir gedacht die links in der Weltrangliste per Schleife durchzugehen. Allerdings fehlt s mir da schon ein wenig daran wie ich das anstelle. Also wie mache ich eine Schleife durch die HTML links. Die sind ja nicht durch nummeriert.

Aber wenn ich so recht überlege habe ich das ja quasi im anderen Code auch schon gemacht. Ich bin die Zeilen durch gegangen und habe geschaut was drin ist. Das müsste ich mal später ausprobieren.

Wozu ich aber gar keine Idee habe. Wie baue ich zum einen meinen Datensatz auf und wie schaffe ich es quasi sagen wir Spalte 1 mit dem Spielernamen und dann spalte 2 - x mit den weiteren daten zu belegen? Macht es sinn die spiele des jeweiligen Spielers von links nach rechts abzu legen oder eher nach unten hinweg. Und macht es nicht sinn immer den Weltrangliste spiel zu den ich die Daten hole in der ersten Spalte abzuspeichern?
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

Man jede Google Suche bleibt erfolglos. Es gibt tausende tutorials wie man irgendwekchen web shops Preise runter scraped. Aber nicht wie man eine Liste mit URL durchforstet...
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Die Tabelle hat den witzigen Klassennamen "table_pranks"
Damit kannst du mit Selenium und der Funktion: find_elements_by_class_name auf die Tabelle zugreifen.

Du bekommst eine Liste mit allen Zeilen.
Die Schleife sieht dann so aus:

Code: Alles auswählen

for row in rows:
    # Zeile auswerten wie im anderen Script auch
Fang doch einfach mal an und zeig uns dann den Punkt wo du nicht mehr weiter kommst.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

so ich habe jetzt mal angefangen, hänge aber direkt:

Code: Alles auswählen

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pandas as pd

driver = webdriver.Chrome('C:\webdrivers\Chromedriver.exe')
driver.get("https://www.tennisergebnisse.net/atp/rangliste/")

rows = driver.find_elements_by_class_name('table_pranks')

for row in rows:
    if "href" in row.get_attribute('class').split():
        player_url = row.find_element_by_css_selector('#body > div:nth-child(5) > div > table > tbody > tr:nth-child(2) > td:nth-child(2) > a').text
  
    print ('player_url')
Da habe ich erstmal eine Frage: wieso reagiert das "print" anders wenn ich es etwas mehr einrücke. Wo gehört es denn richtig hin? Es folgt doch auf das "if" und nicht eingerückt auf player_name = row......

So jetzt mal zu meiner Idee wie ich es umsetzen wollte. Eigentlich hatte ich gedacht ich könnte die url der einzelnen Spieler in eine Liste packen und diese dann anschließend durchlaufen und die entsprechenden Daten holen. Im Ergebnis hätte ich dann eine Tabelle mit folgendem Aufbau

Player;Date;Tournament;home_player;away_player;result;court

Es erscheint mir sinnvoll, dass ich in der ersten Spalte den Spieler mitaufnehme damit ich später in der Exceldatenbank besser filtern kann.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

das hier wäre ein Ansatz mit beautifulsoap

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests
 
r = requests.get('https://www.tennisergebnisse.net/atp/rangliste/')
soup = BeautifulSoup(r.text, 'html.parser')
 
#print(soup.h1.string) 

urls = soup.find_all('href')

for link in soup.find_all('a'):
    print(link.get('href'))  
Erscheint mir sogar einfacher. Hier habe jetzt das Problem: Wie sage ich dem Code das nur die url aus table_pranks angezeigt werden sollen ...
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Mit soup.findall("a") findest du alle a-tags auf der Seite. Das sind zu viele. Du must also zunächst ein übergeordnetes Element sicher finden und dann darunter alle a-tags finden.
In diesem Fall scheint es nur eindeutig über die Textüberschrift der Tabelle zu funktionieren:

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests
 
response = requests.get('https://www.tennisergebnisse.net/atp/rangliste/')
soup = BeautifulSoup(response.text, 'html.parser')

ranking_tables = soup.find_all("div", {"class":"rank_block"})

ranking_table = next(table for table in ranking_tables if table.h2.string == "Weltrangliste Herren")

for a_tag in ranking_table.find_all("a"):
    print(a_tag["href"])
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

Danke schonmal. Bin noch nicht dazu gekommen mir es anzuschauen. Sieht aber in jedem Fall schon mal hilfreich aus.
Ich muss aber nochmal ein step zurück

https://www.oddsportal.com/tennis/polan ... ome-away;2

Gibt es eine Möglichkeit die werte die in der blase erscheinen wenn man mouse over über den Quoten geht auszulesen. Wenn ich die Seite untersuche bekomme ich da nirgends Werte die irgendwie ansprechen könnte.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Ich bin nicht ganz sicher was du meinst. Die orangenen mouseover werden mit JavaScript beim Laden der Seite nachgeladen. Das ist wohl nicht im HTML Quelltext zu finden. Da muss man sich mal mit dem JavaScript Code auseinandersetzen.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

rogerb hat geschrieben: Freitag 17. September 2021, 16:23 Ich bin nicht ganz sicher was du meinst. Die orangenen mouseover werden mit JavaScript beim Laden der Seite nachgeladen. Das ist wohl nicht im HTML Quelltext zu finden. Da muss man sich mal mit dem JavaScript Code auseinandersetzen.
Ja genau die meine ich. Ok dann lassen wir das bin ohnehin schon überfordert. Python weil mir nicht so ganz in den Kopf. Danke
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

Hi Ihr lieben,

hatte jetzt mal wieder etwas Zeit und habe ein wenig an meinem Tool weiter gebastelt.

Hinbekommen habe ich jetzt quasi eine URL zu öffnen. Und die dort aufgelisteten Spiele mit weitern Daten nach Excel zu schreiben. Das funktioniert auch relativ sauber. Hier mein Code:

Code: Alles auswählen

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from openpyxl import Workbook
import pandas as pd

wb = Workbook()
ws = wb.active

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('C:\webdrivers\Chromedriver.exe')
driver.get("https://www.oddsportal.com/matches/tennis/")

loginbtn = driver.find_element_by_xpath('//*[@id="user-header-r2"]/div[1]/button/span/span')
loginbtn.click()

username = driver.find_element_by_xpath('//*[@id="login-username1"]')
username.send_keys("xxusernamexx")

password = driver.find_element_by_xpath('//*[@id="login-password1"]')
password.send_keys("xxpasswortxx")

login = driver.find_element_by_xpath('//*[@id="col-content"]/div[3]/div/form/div[3]/button/span/span')
login.click()

tomorrow = driver.find_element_by_xpath('//*[@id="col-content"]/div[3]/div/div/span/a[3]')
tomorrow.click()

# tabelle mit den Matches
match_table = driver.find_element_by_id("table-matches")
rows = match_table.find_elements_by_tag_name("tr")
    
for row in rows:
        if "dark" in row.get_attribute("class"):
            # dark: alle Zeilen die den Autragungsort enthalten
            cells = row.find_elements_by_tag_name("a")

            data_field_country = cells[0].text.replace("\n", "").strip()
            data_field_tournament = cells[1].text.replace("\n", "").strip()
            
            # usw.

        elif "dark" not in row.get_attribute("class"):
            cells = row.find_elements_by_tag_name("td")

            data_field_time = cells[0].text.replace("\n", "").strip()
            data_field_player = cells[1].text.replace("\n", "").strip()
                    
            if ":" in cells[2].text.replace("\n", "").strip() \
            or "w.o." in cells[2].text.replace("\n", "").strip() \
            or "int." in cells[2].text.replace("\n", "").strip():
                data_field_homeodd = cells[3].text.replace("\n", "").strip()
                data_field_awayodd = cells[4].text.replace("\n", "").strip()
            else:
                data_field_homeodd = cells[2].text.replace("\n", "").strip()
                data_field_awayodd = cells[3].text.replace("\n", "").strip()
            
            #data_field_player_link = ???
            
            #driver.get([data_field_player_link])
            
            for row in driver.find_elements_by_css_selector("#odds-data-table > div:nth-child(1) > table > tbody > tr"):        
                if not "wool" in row.get_attribute("class"):
                    cells = row.find_elements_by_tag_name("td")
                    bookie, home_odd, away_odd, payout = iter_stripped_texts(cells, 0, 4)    

                    ws.append([bookie, home_odd, away_odd, payout])
                    
                    #zurück zur Ursprungsseite und weiter mit den näcchsten daten
            
            
            ws.append([data_field_country ,data_field_tournament , data_field_time , data_field_player , data_field_homeodd , data_field_awayodd])

driver.close()
wb.save("F:\Testdatei\Tennisspiele_morgen.xlsx")
Soweit so gut .... Jetzt möchte ich aber nich während ich die Spiele so nach Excel wegschreibe zusätzlich die Partie anklicken und die dann erscheinenden Quoten und Buchmacher wegschreiben. Ausserhalb des Codes hat das ja noch ganz gut funktioniert. Aber das einbindene in den obigen Code bekomme ich nicht hin.

1. Problem: Wie kann ich die Variable data_field_player_link ermitteln

2. Problem: Wenn ich es schaffen würde die URL der jeweiligen Partie zu öffnen und dort die Daten auslesen könnte, wie komme ich dann wieder zurück an die Stelle wo ich vorher war?

Ich hoffe ich habe mich einigermaßen verständlich ausgedrückt. Im Grunde geht es mir um diesen Part hier:

Code: Alles auswählen

            #data_field_player_link = ???
            
            #driver.get([data_field_player_link])
            
            for row in driver.find_elements_by_css_selector("#odds-data-table > div:nth-child(1) > table > tbody > tr"):        
                if not "wool" in row.get_attribute("class"):
                    cells = row.find_elements_by_tag_name("td")
                    bookie, home_odd, away_odd, payout = iter_stripped_texts(cells, 0, 4)    

                    ws.append([bookie, home_odd, away_odd, payout])
                    
                    #zurück zur Ursprungsseite und weiter mit den näcchsten daten

Es wäre super wenn ihr mir mal wieder helfen könntet .
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

kann man Selenium auch einen URL aus dem HTML Code extrahieren? Oder geht das nur mit beautifulsoap.

Wenn ja wie bekomme dann oben neben dem String im data_field_player auch noch die URL in data_field_player_link?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Assassin4711,
1. Problem: Wie kann ich die Variable data_field_player_link ermitteln
Dazu must du den Link zunächst "manuell" im HTML Code finden und dann kannst du diese Funktionen
https://selenium-python.readthedocs.io/ ... ments.html
verwenden um ihn per Selenium zu finden. Die Seite heißt ja auch "readthedocs" (kleiner Wink mit dem Zaunpfahl) :wink:
Wenn du den Link gefunden hast kannst du ihn wie sonst auch mit Selenium öffnen.
2. Problem: Wenn ich es schaffen würde die URL der jeweiligen Partie zu öffnen und dort die Daten auslesen könnte, wie komme ich dann wieder zurück an die Stelle wo ich vorher war?
Wenn du es einmal geschafft hast zur vorherigen Seite zu kommen, kannst du die gleiche Methode ja wieder verwenden.
kann man Selenium auch einen URL aus dem HTML Code extrahieren? Oder geht das nur mit beautifulsoap.
Das geht mit beiden, siehe oben verlinkte Funktionen für Selenium.
Wenn ja wie bekomme dann oben neben dem String im data_field_player auch noch die URL in data_field_player_link?
Das hängt davon ab wie die URL in den HTML Code eingebettet ist. Ich weiß aber nicht was "data_field_player" sein soll. Daher kann ich nicht mehr dazu sagen.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

@rogerb Danke schonmal für deine Rückmeldung

Das hängt davon ab wie die URL in den HTML Code eingebettet ist. Ich weiß aber nicht was "data_field_player" sein soll. Daher kann ich nicht mehr dazu sagen.
das ganze bezieht dich ja noch auf den vorab aufgeführten Code.
data_field_player ist quasi die Partie in der zu analysierenden tabelle. nur eben als string. dahinter sreckt dann noch dien url due ja eben auch gerne ermittrln würde.
Wenn du es einmal geschafft hast zur vorherigen Seite zu kommen, kannst du die gleiche Methode ja wieder verwenden.
Na du hast gut reden du kannst es ja ... ich habe das Gefühl, je mehr ich lese um so unwissender werde ich. ich schau mir jetzt erstmal das verlinkte Werk an.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

wenn ich doch vorab schon den string gelssen habe also
Spieler a - Spieler b (das wäre dann data_field_players_txt)

könnte ich doch ggfs. hiermit den link finden,oder?

data_field_players_link = driver.find_element_by_partial_link_text(data_field_players_txt)

Oder sehe ich das falsch? bin nicht am pc und kann es nicht testen.

p.s. die seite ist genau das was ich gesucht habe. gibg es sowas auvh für beautifulsoup?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Ich habe den erweiterten Code mit Kommentaren eingefügt. Ich hoffe du findest die Stelle wo es eingefügt werden muss.

Diese Funktionen habe ich verwendet:
https://selenium-python.readthedocs.io/ ... _attribute
https://selenium-python.readthedocs.io/ ... y-tag-name

Code: Alles auswählen

elif "dark" not in row.get_attribute("class"):
    cells = row.find_elements_by_tag_name("td")

    data_field_time = cells[0].text.replace("\n", "").strip()
    data_field_player = cells[1].text.replace("\n", "").strip()

    # erstes a-Tag:
    a_tag = cells[1].find_elements_by_tag_name("a")[0]

    # href Attribut
    url = a_tag.get_attribute("href")

    # die Seite laden
    driver.get(url)

    # jetzt kommt der Teil wo du die Spielerseite auswertest

    # wieder zurück auf die vorige Seite
    driver.get("https://www.oddsportal.com/matches/tennis/")
... ich habe das Gefühl, je mehr ich lese um so unwissender werde ich.
Ja genau, und es wir erst noch viel, viel schlimmer bevor es irgendwann dann wieder leichter und leichter wird. :D Über den Berg muss jeder, der gerne programmieren lernen möchte.
Assassin4711
User
Beiträge: 77
Registriert: Mittwoch 8. September 2021, 14:22

boah vielen vielen Dank ... ich freue mich schon es morgen auszuprobieren.
Ja genau, und es wir erst noch viel, viel schlimmer bevor es irgendwann dann wieder leichter und leichter wird.  Über den Berg muss jeder, der gerne programmieren lernen möchte.
Aber mit so Jungs wie euch, fällt es viel viel leichter ...

Danke euch allen
Antworten