Получите доступ к двум классам, используя find_next_sibling и Beautifulsoup - PullRequest
1 голос
/ 22 марта 2020

Я перебираю паутину. net. В настоящее время я пытаюсь получить текст их «типов», но я могу получить только первый (если вы знаете что-нибудь о покемонах, у некоторых есть два типа: яда, яда ...). Я пытаюсь использовать find_next_sibling, но я не уверен, правильно ли я делаю. Что я могу изменить, чтобы получить оба их типа?

Он внутри блока ..

<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>

Что у меня есть:

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)

Ответы [ 3 ]

0 голосов
/ 22 марта 2020

Проблема с этой строкой ...

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

find получает первый элемент, но вам нужны все типы, поэтому вам нужно find_all. Это даст вам большой список типов и покемонов и не скажет вам, какой тип для какого покемона. Нужно сделать шаг назад, чтобы решить эту проблему.

Нам нужны покемоны и назначенные им типы, поэтому единственная строка этих таблиц стоит данных. Во-первых, давайте возьмем строку ...

rows = dex.find_all('tr')

Затем каждая строка содержит имя и связанные типы для этого покемона. Затем мы можем l oop пройти через все строки и получить эти данные. Полный код для меня это ...

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)
0 голосов
/ 22 марта 2020

Хорошо, слишком много неправильных вещей;

pokemon_types1 объект - это массив, вы должны выполнить итерацию и выполнить операции с каждым элементом в этом массиве. Вы не можете использовать метод .find_next_sibling для array, потому что у объекта array нет метода как find_next_sibling.

А также есть еще одна проблема, которую вы пытаетесь использовать find_next_sibling после того, как вы получите текст в pokemon_types1. Так что это больше не элемент BeautifulSoup, а просто строка.

Вы также получаете дубликаты элементов при использовании type_.find(class_ = 'type-icon').get_text()

enter image description here

Я предлагаю вам использовать что-то подобное:

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)

Вывод

{'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']},
 .
 .
 .
 .

После этого вы можете импортировать его в pandas, извините, я у меня нет опыта работы с pandas, поэтому я не могу дать вам пример, чтобы показать, как это делается.

0 голосов
/ 22 марта 2020

Вам просто нужно повторить ваш types объект:

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

Но на самом деле вы можете просто использовать , выполняя для вас разбор, указав id таблица с использованием read_html:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...