web-dev-qa-db-fra.com

Beautiful Soup: l'objet 'ResultSet' n'a pas d'attribut 'find_all'?

J'essaie de gratter une table simple en utilisant Beautiful Soup. Voici mon code:

import requests
from bs4 import BeautifulSoup

url = 'https://Gist.githubusercontent.com/anonymous/c8eedd8bf41098a8940b/raw/c7e01a76d753f6e8700b54821e26ee5dde3199ab/gistfile1.txt'
r = requests.get(url)

soup = BeautifulSoup(r.text)
table = soup.find_all(class_='dataframe')

first_name = []
last_name = []
age = []
preTestScore = []
postTestScore = []

for row in table.find_all('tr'):
    col = table.find_all('td')

    column_1 = col[0].string.strip()
    first_name.append(column_1)

    column_2 = col[1].string.strip()
    last_name.append(column_2)

    column_3 = col[2].string.strip()
    age.append(column_3)

    column_4 = col[3].string.strip()
    preTestScore.append(column_4)

    column_5 = col[4].string.strip()
    postTestScore.append(column_5)

columns = {'first_name': first_name, 'last_name': last_name, 'age': age, 'preTestScore': preTestScore, 'postTestScore': postTestScore}
df = pd.DataFrame(columns)
df

Cependant, chaque fois que je l'exécute, j'obtiens cette erreur:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-116-a900c2872793> in <module>()
     14 postTestScore = []
     15 
---> 16 for row in table.find_all('tr'):
     17     col = table.find_all('td')
     18 

AttributeError: 'ResultSet' object has no attribute 'find_all'

J'ai lu une douzaine de questions StackOverflow sur cette erreur et je n'arrive pas à comprendre ce que je fais mal.

28
Anton

La variable table contient un tableau. Vous devez appeler find_all sur ses membres (même si vous savez que c'est un tableau avec un seul membre), pas sur le tout.

>>> type(table)
<class 'bs4.element.ResultSet'>
>>> type(table[0])
<class 'bs4.element.Tag'>
>>> len(table[0].find_all('tr'))
6
>>>
36
Ralf Haring
table = soup.find_all(class_='dataframe')

Cela vous donne un ensemble de résultats - c'est-à-dire tous les éléments qui correspondent à la classe. Vous pouvez soit les parcourir ou, si vous savez que vous n'avez qu'un dataFrame, vous pouvez utiliser find à la place. D'après votre code, il semble que ce dernier soit ce dont vous avez besoin pour faire face au problème immédiat:

table = soup.find(class_='dataframe')

Cependant, ce n'est pas tout:

for row in table.find_all('tr'):
    col = table.find_all('td')

Vous voulez probablement parcourir les td de la ligne ici, plutôt que la table entière. (Sinon, vous verrez simplement la première ligne encore et encore.)

for row in table.find_all('tr'):
    for col in row.find_all('td'):
9
otus

Itérer sur la table et utiliser rowfind_all('td')

   for row in table:
        col = row.find_all('td')
1