Skrobak do składów koszykówki
Jestem bardzo nowy w Pythonie i staram się uczyć poprzez osobiste projekty, a dziś potrzebowałem zebrać wiele nazwisk graczy w baksetball i zdecydowałem, że to dobry czas na naukę i praktykę.
Skrypt jest w stanie wyciągnąć wszystkie nazwiska graczy, wzrost, narodowość i datę urodzenia, ale przed uruchomieniem muszę podać link do stron. Następnym krokiem będzie albo zbudowanie interfejsu graficznego, w którym mogę skopiować / wkleić linki lub zapytać w konsoli, czy chcę dołączyć do nowego zespołu.
Nie mogę się doczekać kontaktu z Państwem, ponieważ jest to być może mój pierwszy osobisty projekt :)
import os
import requests
import pandas as pd
import xlsxwriter
from bs4 import BeautifulSoup
def reverse(name):
to_reverse = name
return ' '.join(reversed(name.split(' ')))
def conversion_df(url):
requete = requests.get(url)
page = requete.content
soup = BeautifulSoup(page, features="lxml")
header = [th.getText() for th in soup.findAll("th")] # Why do I have to put th. before getText for it to work | Why do we use th as an updator
header = header[1:5] # Here we exclude the first (O) entry and we display the entries situated before 5
row = soup.findAll("tr")[1:]
stats = [[td.getText().strip() for td in row[i]] for i in range(len(row))]
for j in stats:
del j[0]
del j[4]
#print(stats)
for i in range(len(stats)):
stats[i][0] = reverse(stats[i][0])
table = pd.DataFrame(data = stats, columns = header)
return table
nanterre = conversion_df("https://www.lnb.fr/fr/espa/equipe/espoirs-nanterre-61344.html")
monaco = conversion_df("https://www.lnb.fr/fr/espa/equipe/espoirs-monaco-61343.html")
boulazac = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-boulazac-61331.html")
boulogne = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-boulogne-levallois-61332.html")
bourg = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-bourg-en-bresse-61333.html")
chalon = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-chalon-saone-61334.html")
cholet = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-cholet-61336.html")
chalon_reims = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-chalons-reims-61335.html")
dijon = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-dijon-61337.html")
gravelines = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-gravelines-dunkerque-61338.html")
le_mans = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-le-mans-61339.html")
le_portel = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-le-portel-61340.html")
orleans = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-orleans-61345.html")
pau = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-pau-lacq-orthez-61346.html")
roanne = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-roanne-61347.html")
strasbourg = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-strasbourg-61348.html")
limoges = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-limoges-61341.html")
lyon = conversion_df("https://www.lnb.fr/fr/espoirs/equipe/espoirs-lyon-villeurbanne-61342.html")
clubs = [boulazac,boulogne,bourg,chalon,cholet,chalon_reims,dijon,gravelines,le_mans,le_portel,limoges,lyon,monaco,nanterre,orleans,pau,roanne,strasbourg]
# Creating Excel Writer Object from Pandas
writer = pd.ExcelWriter('liste_espoir.xlsx',engine='xlsxwriter')
workbook=writer.book
worksheet=workbook.add_worksheet('Espoirs')
writer.sheets['Espoirs'] = worksheet
row_count = 0
i = 0
for i in range(len(clubs)):
clubs[i].to_excel(writer,sheet_name='Espoirs',startrow=row_count , startcol=0)
row_count += 20
writer.save()
Odpowiedzi
Witamy w przeglądzie kodu. Wygląda na to, że Twój kod jest zgodny z dobrymi praktykami z przewodnika po stylu Pythona (PEP-8). Jednak jako programista być może możesz poprawić strukturę / wydajność.
- Nie ma potrzeby posiadania oddzielnych zmiennych dla ramek danych dla każdego klubu. Zgrupuj wszystkie linki i użyj
mapdo pobrania wszystkiego. - Funkcja reverse definiuje nieużywane zmienne
to_reverse. - Podziel funkcjonalność, aby oddzielić funkcję, tak jak masz jedną do odwrócenia nazw.
- Nie musisz iterować,
range(len(some_iterable))jeśli indeks nie jest w ogóle potrzebny. - Dodaj podpowiedzi do typów i komentarze do funkcji, aby pomóc zrozumieć, jakich wartości może się spodziewać (i zwracać), a także co robi.
- Umieść wszystko w
if __name__ == "__main__"klauzuli.
Przepisany kod:
from typing import Tuple
import requests
import pandas as pd
import xlsxwriter
from bs4 import BeautifulSoup
def reverse(name: str) -> str:
"""Reverse name from 'Last First' to 'First Last'."""
return " ".join(reversed(name.split(" ")))
def fetch_page(url: str) -> str:
"""Send request to given url, and return the contents on success."""
response = requests.get(url)
if response.ok:
return response.content
def get_club_information(club_page) -> Tuple:
"""Read all `tr` elements on page, and extract player information.
Each row (`tr`) consists of 6 cells. We are skipping over 1st and last cell data."""
soup = BeautifulSoup(club_page, features="lxml")
rows = soup.findAll("tr")
header, *content = [[cell.getText().strip() for cell in row][1:5] for row in rows]
for row in content:
row[0] = reverse(row[0])
return header, content
def conversion_df(url):
page = fetch_page(url)
header, content = get_club_information(page)
print(header, content)
table = pd.DataFrame(data=content, columns=header)
return table
LINKS = (
"https://www.lnb.fr/fr/espa/equipe/espoirs-nanterre-61344.html",
"https://www.lnb.fr/fr/espa/equipe/espoirs-monaco-61343.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-boulazac-61331.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-boulogne-levallois-61332.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-bourg-en-bresse-61333.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-chalon-saone-61334.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-cholet-61336.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-chalons-reims-61335.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-dijon-61337.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-gravelines-dunkerque-61338.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-le-mans-61339.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-le-portel-61340.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-orleans-61345.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-pau-lacq-orthez-61346.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-roanne-61347.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-strasbourg-61348.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-limoges-61341.html",
"https://www.lnb.fr/fr/espoirs/equipe/espoirs-lyon-villeurbanne-61342.html",
)
def main():
# Creating Excel Writer Object from Pandas
writer = pd.ExcelWriter("liste_espoir.xlsx", engine="xlsxwriter")
workbook = writer.book
writer.sheets["Espoirs"] = workbook.add_worksheet("Espoirs")
row_count = 0
for club in map(conversion_df, LINKS):
club.to_excel(writer, sheet_name="Espoirs", startrow=row_count, startcol=0)
row_count += 20
writer.save()
if __name__ == "__main__":
main()
Ponadto możesz użyć asyncio do równoległego pobierania tych stron, aby skrócić czas wykonywania programu.