2
votes

Scraping de tableaux HTML en CSV à l'aide de BS4 pour une utilisation avec Pandas

J'ai commencé un petit projet en créant ce qui est essentiellement une compilation indexée d'une pléthore de statistiques de la NFL avec une interface graphique simple et agréable. Heureusement, le site https://www.pro-football-reference.com a tous les des données que vous pouvez imaginer sous forme de tableaux qui peuvent être exportés au format CSV sur le site et copiés / collés manuellement. J'ai commencé à faire cela, puis à utiliser la bibliothèque Pandas, j'ai commencé à lire les CSV dans DataFrames pour utiliser les données.

Cela fonctionne très bien, cependant, récupérer manuellement toutes ces données est assez fastidieux, j'ai donc décidé d'essayer de créer un racleur Web qui peut extraire des tableaux HTML et les convertir en un format CSV utilisable. J'ai du mal, en particulier pour isoler les tables individuelles, mais aussi pour que le CSV produit soit rendu dans un format lisible / utilisable.

Voici à quoi ressemble le grattoir en ce moment:

table = soup.select_one('table.stats_table')

Cela envoie correctement la requête à l'URL, mais ne récupère pas les données que je recherche qui sont «Rushing_and_Receiving». Au lieu de cela, il récupère le premier tableau de la page «Statistiques et classement de l'équipe». Il rend également le CSV dans un format plutôt laid / pas utile comme celui-ci:

b'',b'',b'',b'Tot Yds & TO',b'',b'',b'Passing',b'Rushing',b'Penalties',b'',b'Average Drive',b'Player',b'PF',b'Yds',b'Ply',b'Y/P',b'TO',b'FL',b'1stD',b'Cmp',b'Att',b'Yds',b'TD',b'Int',b'NY/A',b'1stD',b'Att',b'Yds',b'TD',b'Y/A',b'1stD',b'Pen',b'Yds',b'1stPy',b'#Dr',b'Sc%',b'TO%',b'Start',b'Time',b'Plays',b'Yds',b'Pts',b'Team Stats',b'Opp. Stats',b'Lg Rank Offense',b'Lg Rank Defense'

b'309',b'4944',b'920',b'5.4',b'22',b'8',b'268',b'288',b'474',b'3222',b'27',b'14',b'6.4',b'176',b'415',b'1722',b'8',b'4.1',b'78',b'81',b'636',b'14',b'170',b'30.6',b'12.9',b'Own 27.8',b'2:38',b'5.5',b'29.1',b'1.74'
b'8',b'5',b'',b'',b'8',b'13',b'1',b'',b'12',b'12',b'13',b'5',b'13',b'',b'4',b'6',b'4',b'7',b'',b'',b'',b'',b'',b'1',b'21',b'2',b'3',b'2',b'5',b'4'
b'8',b'10',b'',b'',b'20',b'20',b'7',b'',b'7',b'11',b'31',b'15',b'21',b'',b'11',b'15',b'4',b'15',b'',b'',b'',b'',b'',b'24',b'16',b'5',b'13',b'14',b'15',b'11'

Je sais que mon problème avec la récupération de la table correcte se trouve dans la ligne:

XXX

Je suis ce que je considérerais encore comme un novice en Python, donc si quelqu'un peut m'aider à être capable d'interroger et d'analyser une table spécifique avec BS4 au format CSV, je serais plus que reconnaissant! p>

Merci d'avance!


0 commentaires

3 Réponses :


2
votes

Je contournerais complètement la belle soupe puisque les pandas fonctionnent bien pour ce site. (au moins les 4 premiers tableaux que j'ai passés sous silence) Documentation ici XXX



3
votes

La solution pandas n'a pas fonctionné pour moi à cause de la charge ajax, mais vous pouvez voir dans la console l'URL à partir de laquelle chaque table est chargée et la demander directement. Dans ce cas, l'URL est: https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving

Vous pouvez ensuite obtenir la table directement en utilisant son id rushing_and_receiving.

Cela semble fonctionner.

from bs4 import BeautifulSoup
import requests
import csv

def table_Scrape():
    url = 'https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving'
    req = requests.get(url)
    soup = BeautifulSoup(req.text, 'html.parser')
    table = soup.find('table', id='rushing_and_receiving')
    headers = [th.text for th in table.findAll("tr")[1]]
    body = table.find('tbody')
    with open("out.csv", "w", encoding='utf-8') as f:
        wr = csv.writer(f)
        wr.writerow(headers)
        for data_row in body.findAll("tr"):
            th = data_row.find('th')
            wr.writerow([th.text] + [td.text for td in data_row.findAll("td")])

table_Scrape()


2 commentaires

Hahaha je jure que j'ai essayé de passer soup.find ces mêmes paramètres ('table', id = 'rushing_and_receiving') et j'ai obtenu une erreur de mot-clé inattendue ou quelque chose du genre. J'apprécie vraiment tous les retours des gars!


Ahh je vois ce que tu veux dire, ça ne saisit que quelques tables. Je vais jouer un peu plus avec ces deux solutions et voir ce que je propose et mettre à jour ici si nécessaire.



0
votes

J'aimerais pouvoir créditer ces deux réponses comme étant correctes, car elles sont toutes deux utiles, mais hélas, la deuxième réponse utilisant BeautifulSoup est la meilleure réponse car elle permet d'isoler des tables spécifiques, alors que la nature de la manière Le site est structuré limite l'efficacité de la méthode «read_html» dans Pandas.

Merci à tous ceux qui ont répondu!


0 commentaires