如何有效地将HTML列表解析为字典?

时间:2019-08-15 19:07:30

标签: python beautifulsoup

我想知道如何简化这些混乱的代码并将输出放入漂亮的字典中,而不是元组列表中。我可以更好的方式使用BeautifulSoup吗?

from bs4 import BeautifulSoup as soup
import requests


data = []
sample = []

player_page = requests.get('https://www.premierleague.com/players/10483/Rolando-Aarons/stats')
cont = soup(player_page.content)
for strong_tag in cont.find_all('span', 'stat'):
    sample.append(strong_tag.text)
    tempStats = [x.replace("\r\n",",") for x in sample]
    tempStats = [x.replace("\n","") for x in tempStats]
    tempStats = [x.replace(" ","") for x in tempStats]
    tempStats = [i.split(',', 1) for i in tempStats] 
    tempStats = list(map(lambda sublist: tuple(map(str, sublist)), tempStats))
    tempStats = [tuple(int(item) if item.strip().isnumeric() else item for item in group) for group in tempStats]   
data.append(tempStats)
print(data) 

我想要的输出如下:

PlayerName {stat1: 1, stat2: 2 , stat: 3, etc,etc}

之所以采用这种结构,是因为我可以从多个播放器中提取特定的键并比较值。

2 个答案:

答案 0 :(得分:4)

此脚本将创建页面上找到的所有统计信息的字典:

from bs4 import BeautifulSoup as soup
import requests

player_page = requests.get('https://www.premierleague.com/players/10483/Rolando-Aarons/stats')
cont = soup(player_page.content, 'lxml')

data = dict((k.contents[0].strip(), v.get_text(strip=True)) for k, v in zip(cont.select('.topStat span.stat, .normalStat span.stat'), cont.select('.topStat span.stat > span, .normalStat span.stat > span')))

from pprint import pprint
pprint(data)

打印:

{'Accurate long balls': '8',
 'Aerial battles lost': '12',
 'Aerial battles won': '7',
 'Appearances': '18',
 'Assists': '1',
 'Big chances created': '1',
 'Big chances missed': '0',
 'Blocked shots': '2',
 'Clearances': '11',
 'Cross accuracy %': '21%',
 'Crosses': '19',
 'Duels lost': '67',
 'Duels won': '54',
 'Errors leading to goal': '1',
 'Fouls': '11',
 'Freekicks scored': '0',
 'Goals': '2',
 'Goals per match': '0.11',
 'Goals with left foot': '1',
 'Goals with right foot': '0',
 'Headed Clearance': '6',
 'Headed goals': '1',
 'Hit woodwork': '1',
 'Interceptions': '8',
 'Losses': '12',
 'Offsides': '1',
 'Passes': '197',
 'Passes per match': '10.94',
 'Penalties scored': '0',
 'Recoveries': '43',
 'Red cards': '0',
 'Shooting accuracy %': '27%',
 'Shots': '11',
 'Shots on target': '3',
 'Successful 50/50s': '14',
 'Tackle success %': '70%',
 'Tackles': '20',
 'Through balls': '0',
 'Wins': '3',
 'Yellow cards': '2'}

编辑:要使用玩家名称和他的数据创建字典,您可以执行此操作(data来自上面的脚本):

players = {cont.select_one('.playerDetails .name').get_text(strip=True): data}

from pprint import pprint
pprint(players)

打印:

{'Rolando Aarons': {'Accurate long balls': '8',
                    'Aerial battles lost': '12',
                    'Aerial battles won': '7',
                    'Assists': '1',
                    'Big chances created': '1',
                    'Big chances missed': '0',
                    'Blocked shots': '2',
...and so on.

答案 1 :(得分:1)

您可以使用find_allstatsListBlock div s访问数据:

import requests, re
from bs4 import BeautifulSoup as soup
d = soup(requests.get('https://www.premierleague.com/players/10483/Rolando-Aarons/stats').text, 'html.parser')
new_d = d.find_all('div', {'class':'statsListBlock'})
results = {i.div.text[1:-1]:{c.span.contents[0]:c.span.contents[-2].text for c in i.find_all('div', {'class':'normalStat'})} for i in new_d}
new_results = {a:{re.sub('\s+$', '', c):re.findall('\d+', d)[0] for c, d in b.items()} for a, b in results.items()}

输出:

{'Attack': {'Goals': '2', 'Goals per match': '0', 'Headed goals': '1', 'Goals with right foot': '0', 'Goals with left foot': '1', 'Penalties scored': '0', 'Freekicks scored': '0', 'Shots': '11', 'Shots on target': '3', 'Shooting accuracy %': '27', 'Hit woodwork': '1', 'Big chances missed': '0'}, 'Team Play': {'Assists': '1', 'Passes': '197', 'Passes per match': '10', 'Big chances created': '1', 'Crosses': '19', 'Cross accuracy %': '21', 'Through balls': '0', 'Accurate long balls': '8'}, 'Discipline': {'Yellow cards': '2', 'Red cards': '0', 'Fouls': '11', 'Offsides': '1'}, 'Defence': {'Tackles': '20', 'Tackle success %': '70', 'Blocked shots': '2', 'Interceptions': '8', 'Clearances': '11', 'Headed Clearance': '6', 'Recoveries': '43', 'Duels won': '54', 'Duels lost': '67', 'Successful 50/50s': '14', 'Aerial battles won': '7', 'Aerial battles lost': '12', 'Errors leading to goal': '1'}}

关联名称:

new_result = {d.find('div', {'class':'name t-colour'}).text:new_results}

输出:

{'Rolando Aarons': {'Attack': {'Goals': '2', 'Goals per match': '0', 'Headed goals': '1', 'Goals with right foot': '0', 'Goals with left foot': '1', 'Penalties scored': '0', 'Freekicks scored': '0', 'Shots': '11', 'Shots on target': '3', 'Shooting accuracy %': '27', 'Hit woodwork': '1', 'Big chances missed': '0'}, 'Team Play': {'Assists': '1', 'Passes': '197', 'Passes per match': '10', 'Big chances created': '1', 'Crosses': '19', 'Cross accuracy %': '21', 'Through balls': '0', 'Accurate long balls': '8'}, 'Discipline': {'Yellow cards': '2', 'Red cards': '0', 'Fouls': '11', 'Offsides': '1'}, 'Defence': {'Tackles': '20', 'Tackle success %': '70', 'Blocked shots': '2', 'Interceptions': '8', 'Clearances': '11', 'Headed Clearance': '6', 'Recoveries': '43', 'Duels won': '54', 'Duels lost': '67', 'Successful 50/50s': '14', 'Aerial battles won': '7', 'Aerial battles lost': '12', 'Errors leading to goal': '1'}}}