Я пытаюсь проанализировать эту веб-страницу.

Как показано ниже, каждая страница имеет статистику способностей. В конце концов я пытаюсь разобрать все способности в объект. {{Х0}}

Сначала я начал анализировать одну статистику corners, выполнив:

from bs4 import BeautifulSoup as bs
import requests
url = 'https://fmdataba.com/19/p/1165/lionel-messi/'
page = requests.get(url)
soup = bs(page.content, 'html.parser')
print(soup.prettify())
soup.find({"id": "fm_cro"})

Но это возвращает пустой список.

Может ли кто-нибудь помочь, пожалуйста?

enter image description here

3
Dawn17 24 Июн 2019 в 07:26

4 ответа

Лучший ответ

С bs4 4.7.1 вы можете использовать nth-child(odd) и nth-child(even), чтобы получить разные tds в каждой строке для создания своего диктата; и используйте :has и :contains, чтобы получить правильную таблицу для каждого ключевого слова и построить свой внешний диктат для размещения каждого внутреннего элемента.

import requests
from bs4 import BeautifulSoup as bs

r = requests.get('https://fmdataba.com/19/p/1165/lionel-messi/', headers = {'User-Agent':'Mozilla/5.0'})
soup = bs(r.content, 'lxml')
abilities = ['TECHNICAL', 'MENTAL' , 'PHYSICAL']

def get_abilities(soup, keyword):
    table = soup.select_one('div:has(h3:contains("' + ability + '")) + div > table')
    d = {item.select_one('td:nth-child(odd)').text: int(item.select_one('td:nth-child(even)').text) for item in table.select('tr')}
    return d

results = {}

for ability in abilities:
    results[ability] = get_abilities(soup, ability)

print(results)  

Выход:

enter image description here


Объяснение CSS:

Строка селектора css выглядит следующим образом:

soup.select_one('div:has(h3:contains("' + ability + '")) + div > table')

select_one похож на select в том, что он применяет селектор css внутри объекта супа, но возвращает только первое совпадение.

:has и :contains являются псевдоклассы как :nth-child(). Глядя на рассматриваемый html-файл для первой таблицы способностей, приведено объяснение частей:

Нажмите на изображение, чтобы увеличить его.

enter image description here


Дополнительное чтение:

  1. Селекторы псевдо классов
  2. Смежный брат и сестра комбинатор
  3. Детский комбинатор
  4. Css селекторы вообще
  5. выберите один
4
QHarr 24 Июн 2019 в 08:59

Вы также можете использовать pandas:

import pandas as pd
import requests

url = 'https://fmdataba.com/19/p/1165/lionel-messi/'
page = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})

tables = pd.read_html(page.text)
all_data = {}
for idx, name in [(2, 'TECHNICAL'), (3, 'MENTAL'), (4, 'PHYSICAL')]:
    tbl = tables[idx]
    data = {r[0]: r[1] for _, r in tbl.iterrows()}
    all_data[name] = data

tables[2] - это ТЕХНИЧЕСКАЯ таблица, tables[3] - это таблица MENTAL, а tables[4] - это ФИЗИЧЕСКАЯ таблица.

2
spadarian 24 Июн 2019 в 10:54

На основе документации, find() и { Методы {X1}} не принимают словарь, у них есть необязательный аргумент ключевого слова id, который вы можете использовать.

soup.find(id='fm_cro')

Это даст вам элемент с этим идентификатором (в данном случае <td> с текстом «Пересечение»). Если вы хотите получить связанный номер, вам нужно использовать методы-братья BeautifulSoup, чтобы получить следующий соседний <td> и запросить его текст (номер).

0
Soviut 24 Июн 2019 в 05:07

Вот еще один способ достижения тех же результатов без жесткого кодирования селекторов:

import requests
from bs4 import BeautifulSoup

r = requests.get('https://fmdataba.com/19/p/1165/lionel-messi/', headers={'User-Agent':'Mozilla/5.0'})
soup = BeautifulSoup(r.text, 'lxml')
datadict = {}
for container in ['TECHNICAL','MENTAL','PHYSICAL']:
    elem = soup.select_one(f".panel-heading:contains('{container}') + .panel-body")
    datadict[container] = {item.text:item.find_next_sibling().text for item in elem.select("td.active")}
print(datadict)

Выход:

{'TECHNICAL': {'Corners': '15', 'Crossing': '15', 'Dribbling': '20', 'Finishing': '20', 'First Touch': '19', 'Free Kick': '19', 'Heading': '10', 'Long Shots': '17', 'Long Throws': '4', 'Marking': '4', 'Passing': '20', 'Penalty Taking': '17', 'Tackling': '7', 'Technique': '20'}, 'MENTAL': {'Aggression': '7', 'Anticipation': '19', 'Bravery': '10', 'Composure': '18', 'Concentration': '13', 'Decisions': '20', 'Determination': '20', 'Flair': '20', 'Leadership': '14', 'Off The Ball': '16', 'Positioning': '5', 'Teamwork': '14', 'Vision': '20', 'Work Rate': '7'}, 'PHYSICAL': {'Acceleration': '18', 'Agility': '20', 'Balance': '20', 'Jumping Reach': '6', 'Natural Fitness': '14', 'Pace': '15', 'Stamina': '13', 'Strength': '9'}}
3
robots.txt 24 Июн 2019 в 11:09