#python #web-scraping #beautifulsoup
Вопрос:
Я ищу, чтобы собрать данные для команд за несколько лет в разных странах из https://www.transfermarkt.com/premier-league/startseite/wettbewerb/GB1/plus/?saison_id=2019
Этот сайт является примером того, что я ищу, чтобы очистить, включая таблицу с размером отряда и т. Д. В середине страницы, а также таблицу с данными о совпадениях в правой части страницы. Я использую Красивый суп на питоне.
Вот код, который у меня есть до сих пор:
import pandas as pd
import numpy as np
import requests
import time
from bs4 import BeautifulSoup
import warnings
warnings.filterwarnings('ignore')
#create a dictionary for league and iterate over seasons
dct_GB1 = {}
dct_IT1 = {}
dct_ES1 = {}
dct_L1 = {}
dct_FR1 = {}
dct_PO1 = {}
dct_NL1 = {}
dct_TR1 = {}
dct_BE1 = {}
dct_UKR1 = {}
dct_A1 = {}
dct_GR1 = {}
dct_TS1 = {}
dct_SC1 = {}
dct_KR1 = {}
dct_C1 = {}
dct_PL1 = {}
dct_DK1 = {}
dct_ER1 = {}
dct_RO1 = {}
dct_SE1 = {}
dct_ZYP1 = {}
dct_NO1 = {}
dct_KAS1 = {}
dct_UNG1 = {}
dct_ISR1 = {}
dct_BU1 = {}
dct_WER1 = {}
dct_SLO1 = {}
dct_SL1 = {}
dct_AZ1 = {}
dct_BOS1 = {}
dct_MAL1 = {}
dct_ALB1 = {}
dct_MAZ1 = {}
dct_ARM1 = {}
dct_GE1N = {}
dct_FI1 = {}
dct_MO1N = {}
dct_LET1 = {}
dct_MNE1 = {}
dct_KO1 = {}
dct_LUX1 = {}
dct_LI1 = {}
dct_EST1 = {}
dct_IS1 = {}
dct_WAL1 = {}
dct_FARO = {}
dct_AND1 = {}
dct_IR1 = {}
dct_NIR1 = {}
dct_SMR1 = {}
dct_GI1 = {}
dct_GB2 = {}
dct_ES2 = {}
dct_IT2 = {}
dct_FR2 = {}
dct_L2 = {}
dct_NL2 = {}
dct_TR2 = {}
dct_PO2 = {}
dct_A2 = {}
dct_C2 = {}
dct_BE2 = {}
dct_GRS2 = {}
dct_RO2 = {}
dct_PL2 = {}
dct_UN2 = {}
for m in range(2007,2020):
dct_GB1['df_GB1_%s' % m] = pd.DataFrame()
dct_IT1['df_IT1_%s' % m] = pd.DataFrame()
dct_ES1['df_ES1_%s' % m] = pd.DataFrame()
dct_L1['df_L1_%s' % m] = pd.DataFrame()
dct_FR1['df_FR1_%s' % m] = pd.DataFrame()
dct_PO1['df_PO1_%s' % m] = pd.DataFrame()
dct_NL1['df_NL1_%s' % m] = pd.DataFrame()
dct_TR1['df_TR1_%s' % m] = pd.DataFrame()
dct_BE1['df_BE1_%s' % m] = pd.DataFrame()
dct_UKR1['df_UKR1_%s' % m] = pd.DataFrame()
dct_A1['df_A1_%s' % m] = pd.DataFrame()
dct_GR1['df_GR1_%s' % m] = pd.DataFrame()
dct_TS1['df_TS1_%s' % m] = pd.DataFrame()
dct_SC1['df_SC1_%s' % m] = pd.DataFrame()
dct_KR1['df_KR1_%s' % m] = pd.DataFrame()
dct_C1['df_C1_%s' % m] = pd.DataFrame()
dct_PL1['df_PL1_%s' % m] = pd.DataFrame()
dct_DK1['df_DK1_%s' % m] = pd.DataFrame()
dct_ER1['df_ER1_%s' % m] = pd.DataFrame()
dct_RO1['df_RO1_%s' % m] = pd.DataFrame()
dct_SE1['df_SE1_%s' % m] = pd.DataFrame()
dct_ZYP1['df_ZYP1_%s' % m] = pd.DataFrame()
dct_NO1['df_NO1_%s' % m] = pd.DataFrame()
dct_KAS1['df_KAS1_%s' % m] = pd.DataFrame()
dct_UNG1['df_UNG1_%s' % m] = pd.DataFrame()
dct_ISR1['df_ISR1_%s' % m] = pd.DataFrame()
dct_BU1['df_BU1_%s' % m] = pd.DataFrame()
dct_WER1['df_WER1_%s' % m] = pd.DataFrame()
dct_SLO1['df_SLO1_%s' % m] = pd.DataFrame()
dct_SL1['df_SL1_%s' % m] = pd.DataFrame()
dct_AZ1['df_AZ1_%s' % m] = pd.DataFrame()
dct_BOS1['df_BOS1_%s' % m] = pd.DataFrame()
dct_MAL1['df_MAL1_%s' % m] = pd.DataFrame()
dct_ALB1['df_ALB1_%s' % m] = pd.DataFrame()
dct_MAZ1['df_MAZ1_%s' % m] = pd.DataFrame()
dct_ARM1['df_ARM1_%s' % m] = pd.DataFrame()
dct_GE1N['df_GE1N_%s' % m] = pd.DataFrame()
dct_FI1['df_FI1_%s' % m] = pd.DataFrame()
dct_MO1N['df_MO1N_%s' % m] = pd.DataFrame()
dct_LET1['df_LET1_%s' % m] = pd.DataFrame()
dct_MNE1['df_MNE1_%s' % m] = pd.DataFrame()
dct_KO1['df_KO1_%s' % m] = pd.DataFrame()
dct_LUX1['df_LUX1_%s' % m] = pd.DataFrame()
dct_LI1['df_LI1_%s' % m] = pd.DataFrame()
dct_EST1['df_EST1_%s' % m] = pd.DataFrame()
dct_IS1['df_IS1_%s' % m] = pd.DataFrame()
dct_WAL1['df_WAL1_%s' % m] = pd.DataFrame()
dct_FARO['df_FARO_%s' % m] = pd.DataFrame()
dct_AND1['df_AND1_%s' % m] = pd.DataFrame()
dct_IR1['df_IR1_%s' % m] = pd.DataFrame()
dct_NIR1['df_NIR1_%s' % m] = pd.DataFrame()
dct_SMR1['df_SMR1_%s' % m] = pd.DataFrame()
dct_GI1['df_GI1_%s' % m] = pd.DataFrame()
dct_GB2['df_GB2_%s' % m] = pd.DataFrame()
dct_ES2['df_ES2_%s' % m] = pd.DataFrame()
dct_IT2['df_IT2_%s' % m] = pd.DataFrame()
dct_FR2['df_FR2_%s' % m] = pd.DataFrame()
dct_L2['df_L2_%s' % m] = pd.DataFrame()
dct_NL2['df_NL2_%s' % m] = pd.DataFrame()
dct_TR2['df_TR2_%s' % m] = pd.DataFrame()
dct_PO2['df_PO2_%s' % m] = pd.DataFrame()
dct_A2['df_A2_%s' % m] = pd.DataFrame()
dct_C2['df_C2_%s' % m] = pd.DataFrame()
dct_BE2['df_BE2_%s' % m] = pd.DataFrame()
dct_GRS2['df_GRS2_%s' % m] = pd.DataFrame()
dct_RO2['df_RO2_%s' % m] = pd.DataFrame()
dct_PL2['df_PL2_%s' % m] = pd.DataFrame()
dct_UN2['df_UN2_%s' % m] = pd.DataFrame()
#list of URL bases for each league
league_urls = (['https://www.transfermarkt.com/premier-league/startseite/wettbewerb/GB1/plus/?saison_id=',
'https://www.transfermarkt.com/serie-a/startseite/wettbewerb/IT1/plus/?saison_id=',
'https://www.transfermarkt.com/laliga/startseite/wettbewerb/ES1/plus/?saison_id=',
'https://www.transfermarkt.com/bundesliga/startseite/wettbewerb/L1/plus/?saison_id=',
'https://www.transfermarkt.com/ligue-1/startseite/wettbewerb/FR1/plus/?saison_id=',
'https://www.transfermarkt.com/liga-nos/startseite/wettbewerb/PO1/plus/?saison_id=',
'https://www.transfermarkt.com/eredivisie/startseite/wettbewerb/NL1/plus/?saison_id=',
'https://www.transfermarkt.com/super-lig/startseite/wettbewerb/TR1/plus/?saison_id=',
'https://www.transfermarkt.com/jupiler-pro-league/startseite/wettbewerb/BE1/plus/?saison_id=',
'https://www.transfermarkt.com/premier-liga/startseite/wettbewerb/UKR1/plus/?saison_id=',
'https://www.transfermarkt.com/bundesliga/startseite/wettbewerb/A1/plus/?saison_id=',
'https://www.transfermarkt.com/super-league-1/startseite/wettbewerb/GR1/plus/?saison_id=',
'https://www.transfermarkt.com/fortuna-liga/startseite/wettbewerb/TS1/plus/?saison_id=',
'https://www.transfermarkt.com/scottish-premiership/startseite/wettbewerb/SC1/plus/?saison_id=',
'https://www.transfermarkt.com/1-hnl/startseite/wettbewerb/KR1/plus/?saison_id=',
'https://www.transfermarkt.com/super-league/startseite/wettbewerb/C1/plus/?saison_id=',
'https://www.transfermarkt.com/pko-ekstraklasa/startseite/wettbewerb/PL1/plus/?saison_id=',
'https://www.transfermarkt.com/superligaen/startseite/wettbewerb/DK1/plus/?saison_id=',
'https://www.transfermarkt.com/super-liga-srbije/startseite/wettbewerb/SER1/plus/?saison_id=',
'https://www.transfermarkt.com/liga-1/startseite/wettbewerb/RO1/plus/?saison_id=',
'https://www.transfermarkt.com/allsvenskan/startseite/wettbewerb/SE1/plus/?saison_id=',
'https://www.transfermarkt.com/protathlima-cyta/startseite/wettbewerb/ZYP1/plus/?saison_id=',
'https://www.transfermarkt.com/eliteserien/startseite/wettbewerb/NO1/plus/?saison_id=',
'https://www.transfermarkt.com/premier-liga/startseite/wettbewerb/KAS1/plus/?saison_id=',
'https://www.transfermarkt.com/nemzeti-bajnoksag/startseite/wettbewerb/UNG1/plus/?saison_id=',
'https://www.transfermarkt.com/ligat-haal/startseite/wettbewerb/ISR1/plus/?saison_id=',
'https://www.transfermarkt.com/efbet-liga/startseite/wettbewerb/BU1/plus/?saison_id=',
'https://www.transfermarkt.com/vysheyshaya-liga/startseite/wettbewerb/WER1/plus/?saison_id=',
'https://www.transfermarkt.com/fortuna-liga/startseite/wettbewerb/SLO1/plus/?saison_id=',
'https://www.transfermarkt.com/prva-liga/startseite/wettbewerb/SL1/plus/?saison_id=',
'https://www.transfermarkt.com/premyer-liqa/startseite/wettbewerb/AZ1/plus/?saison_id=',
'https://www.transfermarkt.com/premijer-liga/startseite/wettbewerb/BOS1/plus/?saison_id=',
'https://www.transfermarkt.com/premier-league/startseite/wettbewerb/MAL1/plus/?saison_id=',
'https://www.transfermarkt.com/kategoria-superiore/startseite/wettbewerb/ALB1/plus/?saison_id=',
'https://www.transfermarkt.com/prva-makedonska-fudbalska-liga/startseite/wettbewerb/MAZ1/plus/?saison_id=',
'https://www.transfermarkt.com/bardzragujn-khumb/startseite/wettbewerb/ARM1/plus/?saison_id=',
'https://www.transfermarkt.com/crystalbet-erovnuli-liga/startseite/wettbewerb/GE1N/plus/?saison_id=',
'https://www.transfermarkt.com/veikkausliiga/startseite/wettbewerb/FI1/plus/?saison_id=',
'https://www.transfermarkt.com/divizia-nationala/startseite/wettbewerb/MO1N/plus/?saison_id=',
'https://www.transfermarkt.com/virsliga/startseite/wettbewerb/LET1/plus/?saison_id=',
'https://www.transfermarkt.com/telekom-1-cfl/startseite/wettbewerb/MNE1/plus/?saison_id=',
'https://www.transfermarkt.com/superliga-e-kosoves/startseite/wettbewerb/KO1/plus/?saison_id=',
'https://www.transfermarkt.com/bgl-ligue/startseite/wettbewerb/LUX1/plus/?saison_id=',
'https://www.transfermarkt.com/a-lyga/startseite/wettbewerb/LI1/plus/?saison_id=',
'https://www.transfermarkt.com/premium-liiga/startseite/wettbewerb/EST1/plus/?saison_id=',
'https://www.transfermarkt.com/pepsi-max-deild/startseite/wettbewerb/IS1/plus/?saison_id=',
'https://www.transfermarkt.com/cymru-premier/startseite/wettbewerb/WAL1/plus/?saison_id=',
'https://www.transfermarkt.com/betri-deildin/startseite/wettbewerb/FARO/plus/?saison_id=',
'https://www.transfermarkt.com/primera-divisio/startseite/wettbewerb/AND1/plus/?saison_id=',
'https://www.transfermarkt.com/premier-league/startseite/wettbewerb/IR1/plus/?saison_id=',
'https://www.transfermarkt.com/danske-bank-premiership/startseite/wettbewerb/NIR1/plus/?saison_id=',
'https://www.transfermarkt.com/campionato-sammarinese/startseite/wettbewerb/SMR1/plus/?saison_id=',
'https://www.transfermarkt.com/gibraltar-national-league/startseite/wettbewerb/GI1/plus/?saison_id=',
'https://www.transfermarkt.com/championship/startseite/wettbewerb/GB2/plus/?saison_id=',
'https://www.transfermarkt.com/laliga2/startseite/wettbewerb/ES2/plus/?saison_id=',
'https://www.transfermarkt.com/serie-b/startseite/wettbewerb/IT2/plus/?saison_id=',
'https://www.transfermarkt.com/ligue-2/startseite/wettbewerb/FR2/plus/?saison_id=',
'https://www.transfermarkt.com/2-bundesliga/startseite/wettbewerb/L2/plus/?saison_id=',
'https://www.transfermarkt.com/keuken-kampioen-divisie/startseite/wettbewerb/NL2/plus/?saison_id=',
'https://www.transfermarkt.com/1-lig/startseite/wettbewerb/TR2/plus/?saison_id=',
'https://www.transfermarkt.com/liga-portugal-2/startseite/wettbewerb/PO2/plus/?saison_id=',
'https://www.transfermarkt.com/2-liga/startseite/wettbewerb/A2/plus/?saison_id=',
'https://www.transfermarkt.com/challenge-league/startseite/wettbewerb/C2/plus/?saison_id=',
'https://www.transfermarkt.com/proximus-league/startseite/wettbewerb/BE2/plus/?saison_id=',
'https://www.transfermarkt.com/super-league-2/startseite/wettbewerb/GRS2/plus/?saison_id=',
'https://www.transfermarkt.com/liga-2/startseite/wettbewerb/RO2/plus/?saison_id=',
'https://www.transfermarkt.com/fortuna-1-liga/startseite/wettbewerb/PL2/plus/?saison_id=',
'https://www.transfermarkt.com/nemzeti-bajnoksag-ii-/startseite/wettbewerb/UN2/plus/?saison_id='])
Это моя настройка со всеми URL-адресами для повторения в течение каждого сезона. Затем я пытаюсь извлечь данные, используя приведенный ниже код:
#Scraping part
#The first loop is for each url in our URL-list
for m in range(0, len(league_urls)):
time.sleep(0.5)
#The second loop is for each year we want to scrape
for n in range(2007,2020):
time.sleep(0.5)
df_soccer1 = None
url = league_urls[m] str(n)
headers = {"User-Agent":"Mozilla/5.0"}
response = requests.get(url, headers=headers, verify=False)
time.sleep(0.5)
soup = BeautifulSoup(response.text, 'html.parser')
#Table 1 with information about the value
table = soup.find("table", {"class" : "items"})
team = []
squad = []
age = []
foreigners = []
total_market_value = []
average_market_value = []
for row in table.findAll('tr'):
try:
col = row.findAll('td')
team.append(col[2].text)
squad.append(col[3].text)
age.append(col[4].text)
foreigners.append(col[5].text)
total_market_value.append(col[6].text)
average_market_value.append(col[7].text)
except:
pass
team = [elem.replace('n','').replace('xa0','').strip() for elem in team]
#Table 2 with information about placement, goals and points
df_soccer2 = None
table2 = soup.findAll("div", {"class" : "responsive-table"})
team2 = []
place = []
matches = []
difference = []
pts = []
if len(table2) <= 2:
for row in table2[1].findAll('tr'):
try:
col = row.findAll('td')
team2.append(col[2].text)
place.append(col[0].text)
matches.append(col[3].text)
difference.append(col[4].text)
pts.append(col[5].text)
except:
pass
else:
#Sometimes the information you need is in another table
for row in table2[2].findAll('tr'):
try:
col = row.findAll('td')
team2.append(col[2].text)
place.append(col[0].text)
matches.append(col[3].text)
difference.append(col[4].text)
pts.append(col[5].text)
except:
pass
team2 = [elem.replace('n','').replace('xa0','').strip() for elem in team2]
df_soccer1 = pd.DataFrame({'Team': team[1:], 'Season': n, 'Squad': squad[1:], 'Age': age[1:], 'Foreigners': foreigners[1:],
'Total Value': total_market_value[1:], 'Average value': average_market_value[1:]})
df_soccer2 = pd.DataFrame({'Team': team2, 'Place': place, 'Matches': matches, 'Difference': difference,
'Points': pts})
#Store all dictionaries in a list
dct_all = [dct_GB1,dct_IT1,dct_ES1,dct_L1,dct_FR1,dct_PO1,dct_NL1,dct_TR1,dct_BE1,dct_UKR1,dct_A1,
dct_GR1,dct_TS1,dct_SC1,dct_KR1,dct_C1,dct_PL1,dct_DK1,dct_ER1,dct_RO1,dct_SE1,dct_ZYP1,dct_NO1,
dct_KAS1,dct_UNG1,dct_ISR1,dct_BU1,dct_WER1,dct_SLO1,dct_SL1,dct_AZ1,dct_BOS1,dct_MAL1,dct_ALB1,
dct_MAZ1,dct_ARM1,dct_GE1N,dct_FI1,dct_MO1N,dct_LET1,dct_MNE1,dct_KO1,dct_LUX1,dct_LI1,dct_EST1,
dct_IS1,dct_WAL1,dct_FARO,dct_AND1,dct_IR1,dct_NIR1,dct_SMR1,dct_GI1,dct_GB2,dct_ES2,dct_IT2,
dct_FR2,dct_L2,dct_NL2,dct_TR2,dct_PO2,dct_A2,dct_C2,dct_BE2,dct_GRS2,dct_RO2,dct_PL2,dct_UN2]
#Merge df_soccer1 and df_soccer2 for each season
dct_all[l]['df_bl_%s' % n] = pd.merge(df_soccer1, df_soccer2, how="inner", left_on="Team", right_on="Team")
Проблема в том, что я получаю ошибку:
Ошибка значения: все массивы должны быть одинаковой длины
Я понял, что получаю это, так как для некоторых команд/стран не каждый год доступно. Есть ли решение этой проблемы, при котором я могу очистить все данные и просто заполнить пробелы за недостающие годы?’
Редактировать:
Вот ошибка, которую я получаю
--------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-7-534e3145bb5f> in <module>
50
51
---> 52 df_soccer1 = pd.DataFrame({'Team': team[1:], 'Season': n, 'Squad': squad[1:], 'Age': age[1:], 'Foreigners': foreigners[1:],
53 'Total Value': total_market_value[1:], 'Average value': average_market_value[1:]})
54
~anaconda3libsite-packagespandascoreframe.py in __init__(self, data, index, columns, dtype, copy)
527
528 elif isinstance(data, dict):
--> 529 mgr = init_dict(data, index, columns, dtype=dtype)
530 elif isinstance(data, ma.MaskedArray):
531 import numpy.ma.mrecords as mrecords
~anaconda3libsite-packagespandascoreinternalsconstruction.py in init_dict(data, index, columns, dtype)
285 arr if not is_datetime64tz_dtype(arr) else arr.copy() for arr in arrays
286 ]
--> 287 return arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)
288
289
~anaconda3libsite-packagespandascoreinternalsconstruction.py in arrays_to_mgr(arrays, arr_names, index, columns, dtype, verify_integrity)
78 # figure out the index, if necessary
79 if index is None:
---> 80 index = extract_index(arrays)
81 else:
82 index = ensure_index(index)
~anaconda3libsite-packagespandascoreinternalsconstruction.py in extract_index(data)
399 lengths = list(set(raw_lengths))
400 if len(lengths) > 1:
--> 401 raise ValueError("arrays must all be same length")
402
403 if have_dicts:
ValueError: arrays must all be same length
Ответ №1:
Было бы полезно, если бы вы указали, какая часть вашего кода выдает ошибку. Я предполагаю, что это та часть, где вы инициализируетесь df_soccer1
.
Ваша проблема в том, что try:
выполняется до тех пор , пока этого не произойдет , что означает , что если в a всего 5 <td>
<tr>
, к нему добавляется текст team
, squad
а age
затем возникает ошибка, потому что вы повторяете больше <td>
, чем есть, и ничего не добавляется к foreigners
двум другим точкам данных. Это означает, что ваши массивы имеют неравномерную длину.
Следующий код разделяет шаги, сначала он извлекает текст из всех <td>
, и только если все они были возвращены, информация добавляется, добавляется «еще».
for row in table.findAll('tr'):
try:
col = row.findAll('td')
team_ = col[2].text
squad_ = col[3].text
age_ = col[4].text
foreigners_ = col[5].text
total_ = col[6].text
average_ = col[7].text
team.append(team_)
squad.append(squad_)
age.append(age_)
foreigners.append(foreigners_)
total_market_value.append(total_)
average_market_value.append(average_)
except:
team.append('')
squad.append('')
age.append('')
foreigners.append('')
total_market_value.append('')
average_market_value.append('')
Вы также можете использовать try/except (или более эффективно, если/иначе) для каждой из шести точек данных в отдельности, однако вам нужно быть осторожным, если строки, которые не работают должным образом, действительно содержат интересующую вас информацию.
Комментарии:
1. Я отредактировал свой пост, чтобы включить сообщение об ошибке