Очистка данных с веб-сайта со сложной структурой

Я пытаюсь очистить данные с веб-сайта TransferMarkt на Python. Однако структура сайта сложна. Я пробовал использовать запросы и модули Beautiful Soup, а также следующий код. Однако конечный результат, который я получаю, — это два пустых фрейма данных для «входящих» и «исходящих» передач. Я хочу извлечь информацию из таблиц (показанных на рисунке) в два отдельных фрейма данных. In_transfers_df должен содержать информацию, отображаемую в таблицах «In», а out_transfers_df должен содержать информацию, отображаемую в таблице «Out». Это следует повторить для каждого заголовка, например. Арсенал, Астон Вилла

Я приложил фотографию, показывающую структуру веб-сайта и мою попытку кода. Любая помощь будет принята с благодарностью.

import requests
from bs4 import BeautifulSoup
import pandas as pd

# URL of the Transfermarkt page
url = 'https://www.transfermarkt.com/premier-league/transfers/wettbewerb/GB1/plus/?saison_id=2023&s_w=&leihe=0&intern=0'

# Send a GET request to the URL
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
response = requests.get(url, headers=headers)
response.raise_for_status()  # Raise an exception if the request was unsuccessful

# Parse the page content using BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')

# Function to extract transfer data
def extract_transfer_data(table):
    transfers = []
    rows = table.find_all('tr', class_=['odd', 'even'])
    for row in rows:
        cols = row.find_all('td')
        if len(cols) >= 5:  # Ensure there are enough columns
            transfers.append({
                'Player': cols[0].text.strip(),
                'Age': cols[1].text.strip(),
                'Club': cols[2].text.strip(),
                'Fee': cols[4].text.strip()
            })
    return transfers

# Locate the main transfer table container
transfer_containers = soup.find_all('div', class_='grid-view')

# Debugging: print the number of transfer containers found
print(f"Found {len(transfer_containers)} transfer containers.")

# Extract 'In' and 'Out' transfers data
in_transfers = []
out_transfers = []

for container in transfer_containers:
    headers = container.find_all('h2')
    tables = container.find_all('table')
    for header, table in zip(headers, tables):
        if 'In' in header.text:
            in_transfers.extend(extract_transfer_data(table))
        elif 'Out' in header.text:
            out_transfers.extend(extract_transfer_data(table))

# Convert to DataFrames
in_transfers_df = pd.DataFrame(in_transfers)
out_transfers_df = pd.DataFrame(out_transfers)

Вы забыли задать свой вопрос.

baduker 28.06.2024 13:42

Извините, мой отредактированный вопрос лучше объясняет, что я хотел бы сделать?

Stuart Macfarlane 28.06.2024 14:19

ты сам написал этот код?

GTK 28.06.2024 20:02

Да, но я использовал руководство, которому следовал в Интернете, почему оно актуально? Если это не так, то поэтому я и задаю вопрос

Stuart Macfarlane 30.06.2024 13:22

потому что код не имеет смысла? на странице нет классов нечетного/четного или сетки, нет заголовков, содержащих «отправление» или «прибытие»?

GTK 30.06.2024 17:49
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
5
109
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как правильно заметил @GTK, ваше руководство устарело. Если присмотреться внимательнее, то теперь нужные вам данные находятся в элементах div с классом box. Именно за них и нужно «цепляться», чтобы получить необходимые данные.

Однако, если не считать таких элементов, это может быть не то, что мы ищем. Например, этот блок также имеет аналогичную структуру. Итак, вы должны быть осторожны.

Итак, если вам нужна помощь, вот решение, которое я набросал на лету, и которое подойдет вам. Однако вам следует делать это шаг за шагом и понимать, как это в конечном итоге работает. Улучшите обработку ошибок, а также при необходимости загрузите данные в pandas.

from collections import defaultdict
from pprint import pprint

import requests
from bs4 import BeautifulSoup

start_url = (
    'https://www.transfermarkt.com/premier-league/transfers/wettbewerb/GB1/'
    'plus/?saison_id=2023&s_w=&leihe=0&intern=0'
)
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
response = requests.get(start_url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')


def extract_club_name(node):
    try:
        return node.find('a')['title']
    except (TypeError, KeyError):
        return None


def parse_transfers_table(node):
    for tr in node.find('tbody').find_all('tr'):
        national = tr.find('td', class_='nat-transfer-cell')
        prev_club_data = tr.find(
            'td',
            class_='no-border-links verein-flagge-transfer-cell',
        )
        previous_club = (
            '' if prev_club_data.find('a') is None
            else prev_club_data.find('a')['title']
        )

        yield {
            'name': tr.find('span').find('a')['title'],
            'age': tr.find('td', class_='alter-transfer-cell').text,
            'national': [c['title'] for c in national if c.has_attr('title')],
            'position': tr.find('td', class_='kurzpos-transfer-cell').text,
            'market_price': tr.find('td', class_='mw-transfer-cell').text,
            'previous_club': previous_club,
            'transfer_value': tr.find('td', class_='rechts').text,
        }


result = defaultdict(defaultdict)
for club_info in soup.find_all('div', class_='box'):
    club_name = extract_club_name(club_info)
    if club_name is None:
        continue

    in_transfers_table, out_transfers_table = (
        club_info.find_all('div', class_='responsive-table')
    )
    result[club_name]['in'] = [*parse_transfers_table(in_transfers_table)]
    result[club_name]['out'] = [*parse_transfers_table(out_transfers_table)]

pprint(result)

Да, мне действительно нужна была помощь, и я благодарю вас за ответ. Это очень полезно

Stuart Macfarlane 03.07.2024 23:32

Замечательно! В таком случае, возможно, вам стоит принять ответ?

Serhii Fomenko 04.07.2024 14:55

Другие вопросы по теме