Skrobak do składów koszykówki

Sep 24 2020

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

4 hjpotter92 Sep 25 2020 at 05:00

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ść.

  1. Nie ma potrzeby posiadania oddzielnych zmiennych dla ramek danych dla każdego klubu. Zgrupuj wszystkie linki i użyj mapdo pobrania wszystkiego.
  2. Funkcja reverse definiuje nieużywane zmienne to_reverse.
  3. Podziel funkcjonalność, aby oddzielić funkcję, tak jak masz jedną do odwrócenia nazw.
  4. Nie musisz iterować, range(len(some_iterable))jeśli indeks nie jest w ogóle potrzebny.
  5. 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.
  6. 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.