Очистить таблицы данных с сайта, используя имена - PullRequest
4 голосов
/ 25 января 2020

У меня уникальная ситуация, когда я пытаюсь почистить сайт. Я ищу сотни имен через панель поиска и затем очищаю таблицы. однако некоторые имена являются уникальными и пишутся по-разному в моем списке по сравнению с сайтом. в таких случаях я вручную искал пару имен на сайте, и он по-прежнему переносил меня непосредственно на отдельную страницу. в других случаях, это идет к списку имен, если есть несколько парней с одинаковыми или похожими именами (в этом случае я хочу, чтобы человек, который играл в НБА. Я уже учел это, но я думаю, что необходимо упомянуть ). как мне go по-прежнему заходить на отдельные страницы этих игроков вместо того, чтобы каждый раз запускать скрипт и нажимать на ошибку, чтобы увидеть, какой игрок имеет немного другое правописание? опять же, имя в массиве приведет вас непосредственно к отдельной странице, даже если оно написано немного по-другому или в списке имен (нужен в NBA). Вот некоторые примеры: Георг ios Пападжаннис (указан на веб-сайте как Джордж Пападжаннис), Огнен Кузми c (указан как Огнен Кузми c), Нене (указан как Майбайнер Нене, но приведет вас к списку имен - https://basketball.realgm.com/search?q=nene). это кажется довольно сложным, но я чувствую, что это возможно. Кроме того, кажется, что вместо того, чтобы записывать все очищенные данные в CSV, они перезаписываются каждый раз следующим игроком. спасибо огромное.

ошибка, которую я получаю: AttributeError: 'NoneType' object has no attribute 'text'

import requests
from bs4 import BeautifulSoup
import pandas as pd


playernames=['Carlos Delfino', 'Nene', 'Yao Ming', 'Marcus Vinicius', 'Raul Neto', 'Timothe Luwawu-Cabarrot']

result = pd.DataFrame()
for name in playernames:

    fname=name.split(" ")[0]
    lname=name.split(" ")[1]
    url="https://basketball.realgm.com/search?q={}+{}".format(fname,lname)
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    if soup.find('a',text=name).text==name:
        url="https://basketball.realgm.com"+soup.find('a',text=name)['href']
        print(url)
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'lxml')

    try:
        table1 = soup.find('h2',text='International Regular Season Stats - Per Game').findNext('table')
        table2 = soup.find('h2',text='International Regular Season Stats - Advanced Stats').findNext('table')

        df1 = pd.read_html(str(table1))[0]
        df2 = pd.read_html(str(table2))[0]

        commonCols = list(set(df1.columns) & set(df2.columns))
        df = df1.merge(df2, how='left', on=commonCols)
        df['Player'] = name
        print(df)
    except:
        print ('No international table for %s.' %name)
        df = pd.DataFrame([name], columns=['Player'])

result = result.append(df, sort=False).reset_index(drop=True)

cols = list(result.columns)
cols = [cols[-1]] + cols[:-1]
result = result[cols]
result.to_csv('international players.csv', index=False)

1 Ответ

2 голосов
/ 26 января 2020

Я использовал l oop для игроков NBA с похожими именами. Вы можете найти ниже css селектор ниже, чтобы получить игроков NBA из таблицы поиска:

.tablesaw tr:has(a[href*="/nba/teams/"]) a[href*="/player/"]

CSS селектор, означающий : найти таблицу по классу tablesaw, найти детей таблицы tr с детьми a, чей href содержит /nba/teams/ текст, затем найдите a, чей href содержит /player/

Я добавил Поиск имени игрока и Реальное имя игрока столбцы, которые вы можете увидеть, как был найден игрок. Этот столбец размещается как первый и второй столбец с использованием insert (см. Комментарий в коде).

import requests
from bs4 import BeautifulSoup
import pandas as pd
from pandas import DataFrame

base_url = 'https://basketball.realgm.com'
player_names = ['Carlos Delfino', 'Nene', 'Yao Ming', 'Marcus Vinicius', 'Raul Neto', 'Timothe Luwawu-Cabarrot']

result = pd.DataFrame()


def def get_player_stats(search_name = None, real_name = None, player_soup = None):
    table_per_game = player_soup.find('h2', text='International Regular Season Stats - Per Game')
    table_advanced_stats = player_soup.find('h2', text='International Regular Season Stats - Advanced Stats')

    if table_per_game and table_advanced_stats:
        print('International table for %s.' % search_name)

        df1 = pd.read_html(str(table_per_game.findNext('table')))[0]
        df2 = pd.read_html(str(table_advanced_stats.findNext('table')))[0]

        common_cols = list(set(df1.columns) & set(df2.columns))
        df = df1.merge(df2, how='left', on=common_cols)

        # insert name columns for the first positions
        df.insert(0, 'Search Player Name', search_name)
        df.insert(1, 'Real Player Name', real_name)
    else:
        print('No international table for %s.' % search_name)
        df = pd.DataFrame([[search_name, real_name]], columns=['Search Player Name', 'Real Player Name'])

    return df


for name in player_names:
    url = f'{base_url}/search?q={name.replace(" ", "+")}'
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    if url == response.url:
        # Get all NBA players
        for player in soup.select('.tablesaw tr:has(a[href*="/nba/teams/"]) a[href*="/player/"]'):
            response = requests.get(base_url + player['href'])
            player_soup = BeautifulSoup(response.content, 'lxml')
            player_data = get_player_stats(search_name=player.text, real_name=name, player_soup=player_soup)
            result = result.append(player_data, sort=False).reset_index(drop=True)
    else:
        player_data = get_player_stats(search_name=name, real_name=name, player_soup=soup)
        result = result.append(player_data, sort=False).reset_index(drop=True)

result.to_csv('international players.csv', index=False)
# Append to existing file
# result.to_csv('international players.csv', index=False, mode='a')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...