1
votes

Accédez à deux classes en utilisant find_next_sibling avec beautifulsoup

Je fais du web-scraping sur pokemondb.net. J'essaie actuellement d'obtenir le texte de leurs «types», mais je ne peux obtenir que le premier (si vous savez quelque chose sur Pokemon, certains ont deux types, yada, yada ...). J'essaye d'utiliser find_next_sibling, mais je ne sais pas si je le fais correctement. Que puis-je changer pour récupérer leurs deux types?

C'est à l'intérieur du bloc ..

import pandas as pd
from bs4 import BeautifulSoup

page = requests.get('https://pokemondb.net/pokedex/all')
soup = BeautifulSoup(page.content, 'html.parser')
dex = soup.find(id = 'pokedex')

pokes = (dex.find_all(class_='cell-name'))
types = (dex.find_all(class_='cell-icon'))

pokemon_names = [poke.find(class_ = 'ent-name').get_text() for poke in pokes]
pokemon_types1 = [type_.find(class_ = 'type-icon').get_text() for type_ in types]

pokemon_types2 = [pokemon_types1.find_next_sibling(class_ = 'type-icon').get_text() ]

print(pokemon_types2)

Ce que j'ai jusqu'à présent:

<td class="cell-icon">
<a class="type-icon type-grass" href="/type/grass">Grass</a><br> 
<a class="type-icon type-poison" href="/type/poison">Poison</a>
</td>


0 commentaires

3 Réponses :


0
votes

Il vous suffit d'itérer votre objet types :

import pandas as pd
import requests

r = requests.get("https://pokemondb.net/pokedex/all")

dex = pd.read_html(r.text, attrs = {'id': 'pokedex'})

print(dex)

Mais en réalité, vous pouvez simplement utiliser faire l'analyse pour vous en spécifiant l ' id de la table en utilisant read_html :

pokemon_types = [type_.get_text() for type_ in types]
print(pokemon_types)


0 commentaires

0
votes

Le problème vient de cette ligne ...

from bs4 import BeautifulSoup

page = requests.get('https://pokemondb.net/pokedex/all')
soup = BeautifulSoup(page.content, 'html.parser')
dex = soup.find(id = 'pokedex')

rows = dex.find_all('tr')

for row in rows:
    pokes = (row.find_all(class_='cell-name'))
    types = (row.select('.cell-icon .type-icon'))
    pokemon_names = [poke.find(class_='ent-name').get_text() for poke in pokes]
    pokemon_types = [type_.get_text() for type_ in types]
    print(pokemon_names)
    print(pokemon_types)

find obtient le premier élément, mais vous voulez tous les types donc vous avez besoin de find_all code >. Cela vous donnera ensuite une grande liste de types et de Pokémon et ne vous dira pas quel type est pour quel Pokémon. Il faut prendre du recul pour résoudre ce problème.

Nous voulons que le Pokémon et les types qui lui sont assignés, donc une seule ligne de ces tables vaut des données. Tout d'abord, prenons la ligne ...

rows = dex.find_all('tr')

Ensuite, chaque ligne contient le nom et les types associés pour ce Pokémon. Nous pouvons ensuite parcourir toutes les lignes et récupérer ces données. Le code complet pour cela pour moi est ...

pokemon_types1 = [type_.find(class_ = 'type-icon').get_text() for type_ in types]


0 commentaires

0
votes

Ok, il y a trop de choses qui ne vont pas;

pokemon_types1 objet est un tableau, vous devriez les itérer et faire les opérations sur chaque élément de ce tableau. Vous ne pouvez pas utiliser la méthode .find_next_sibling sur un array car l'objet array n'a pas de méthode comme find_next_sibling .

Et il y a aussi un autre problème, vous essayez d'utiliser find_next_sibling après avoir obtenu le texte dans pokemon_types1 . Ce n'est donc plus un élément BeautifulSoup, c'est juste une chaîne.

Vous obtenez également des éléments en double lorsque vous utilisez type_.find (class_ = 'type-icon'). Get_text () code>

 entrez la description de l'image ici

Je vous suggère d'utiliser quelque chose comme ça:

{'Abomasnow': {'types': ['Grass', 'Ice']},
 'Abra': {'types': ['Psychic']},
 'Absol': {'types': ['Dark']},
 'Accelgor': {'types': ['Bug']},
 'Aegislash': {'types': ['Steel', 'Ghost']},
 'Aerodactyl': {'types': ['Rock', 'Flying']},
 'Aggron': {'types': ['Steel']},
 'Aipom': {'types': ['Normal']},
 'Alakazam': {'types': ['Psychic']},
 'Alcremie': {'types': ['Fairy']},
 'Alomomola': {'types': ['Water']},
 'Altaria': {'types': ['Dragon', 'Fairy']},
 'Amaura': {'types': ['Rock', 'Ice']},
 'Ambipom': {'types': ['Normal']},
 'Amoonguss': {'types': ['Grass', 'Poison']},
 'Ampharos': {'types': ['Electric', 'Dragon']},
 'Anorith': {'types': ['Rock', 'Bug']},
 .
 .
 .
 .
Sortie
from bs4 import BeautifulSoup
import requests

page = requests.get('https://pokemondb.net/pokedex/all')
soup = BeautifulSoup(page.content, 'html.parser')
dex = soup.find(id = 'pokedex').find("tbody")

rows = dex.find_all("tr")

poke_dex = {}

for row in rows:
    poke_name = row.find(class_ = "ent-name").get_text()
    poke_dex[poke_name] = {}
    poke_dex[poke_name]["types"] = [i.get_text() for i in row.find_all(class_ = 'type-icon')]

print(poke_dex)

Après cela, vous pouvez l'importer dans les pandas, désolé je n'ai aucune expérience avec les pandas donc je ne peux pas vous donner d'exemple pour montrer comment procéder.


2 commentaires

salut bonjour cher Guven - je veux relancer votre code d'exemple de réponse et je reviens sur un ATOM fraîchement installé sur Win 10 le «Fichier» C: \ Users \ Kasper \ Documents_mk__dev_ \ python_examples_ \ panda.p‌ Y ", line 17 print (poke_dex) from bs4 import BeautifulSoup ^ SyntaxError: syntaxe invalide [Terminé en 0,214s] ´ ce qui ne va pas ici


Etes-vous sûr que la ligne 17 n'est pas print (poke_dex) depuis bs4 import BeautifulSoup ?