Mencoba membuat dict yang memuat nama, posisi dan nomor untuk setiap pemain untuk setiap tim. Tetapi ketika mencoba membuat kamus terakhir players[team_name] =dict(zip(number,name,position)) itu menimbulkan kesalahan (lihat di bawah). Sepertinya saya tidak bisa melakukannya dengan benar, setiap pemikiran tentang apa yang saya lakukan salah di sini akan sangat dihargai. Terimakasih banyak,

from bs4 import BeautifulSoup as soup
import requests
from lxml import html


clubs_url = 'https://www.premierleague.com/clubs'
parent_url = clubs_url.rsplit('/', 1)[0]
data = requests.get(clubs_url).text
html = soup(data, 'html.parser')

team_name = []
team_link = []

for ul in html.find_all('ul', {'class': 'block-list-5 block-list-3-m block-list-1-s block-list-1-xs block-list-padding dataContainer'}):
    for a in ul.find_all('a'):
        team_name.append(str(a.h4).split('>', 1)[1].split('<')[0])
        team_link.append(parent_url+a['href'])
team_link = [item.replace('overview', 'squad') for item in team_link]
team = dict(zip(team_name, team_link))

data = {}
players = {}

for team_name, team_link in team.items():
    player_page = requests.get(team_link)
    cont = soup(player_page.content, 'lxml')
    clud_ele = cont.find_all('span', attrs={'class' : 'playerCardInfo'})
    for i in clud_ele:
        v_number = [100 if v == "-" else v.get_text(strip=True) for v in i.select('span.number')]
        v_name = [v.get_text(strip=True) for v in i.select('h4.name')]
        v_position = [v.get_text(strip=True) for v in i.select('span.position')]
        key_number = [key for element in i.select('span.number') for key in element['class']]
        key_name = [key for element in i.select('h4.name') for key in element['class']]
        key_position = [key for element in i.select('span.position') for key in element['class']]
        number = dict(zip(key_number,v_number))
        name = dict(zip(key_name,v_name))
        position = dict(zip(key_position,v_name))
        players[team_name] = dict(zip(number,name,position))

---> 21         players[team_name] = dict(zip(number,name,position))
     22 
     23 

ValueError: dictionary update sequence element #0 has length 3; 2 is required
0
MisterButter 1 Februari 2020, 20:40

2 jawaban

Jawaban Terbaik

Ada banyak masalah dalam kode Anda. Yang menyebabkan kesalahan adalah Anda mencoba membuat instance kamus dengan daftar Tuple 3-item dalam daftar yang tidak mungkin. Lihat dokumen dict untuk detailnya.


Yang mengatakan, saya akan menyarankan untuk mengerjakan ulang seluruh loop bersarang.

Pertama, Anda memiliki clud_ele daftar info pemain, setiap info pemain hanya menyangkut satu pemain dan hanya menyediakan satu posisi, hanya satu nama, dan hanya satu nomor. Jadi tidak perlu menyimpan informasi tersebut dalam daftar, Anda dapat menggunakan variabel sederhana:

for player_info in clud_ele:
    number = player_info.select('span.number')[0].get_text(strip=True)
    if number == '-':
        number = 100
    name = player_info.select('h4.name')[0].get_text(strip=True)
    position = player_info.select('span.position')[0].get_text(strip=True)

Di sini, penggunaan metode select mengembalikan daftar tetapi karena Anda tahu bahwa daftar tersebut hanya berisi satu item, tidak masalah untuk mengaktifkan item ini untuk memanggil get_text. Tetapi Anda dapat memeriksa apakah panjang player_info.select('span.number') sebenarnya adalah 1 sebelum melanjutkan bekerja jika Anda ingin memastikan...

Dengan cara ini, Anda mendapatkan tipe data skalar yang akan lebih mudah untuk dimanipulasi. Perhatikan juga bahwa saya mengganti nama i menjadi player_info yang jauh lebih eksplisit.

Kemudian Anda dapat dengan mudah menambahkan data pemain ke dikte players Anda:

players[team_name].append({'name': name,
                           'position': position
                           'number': number})

Ini mengasumsikan bahwa Anda membuat players[team_name] sebelum loop bersarang dengan players[team_name] = [].

Sunting: seperti yang dinyatakan dalam jawaban @kederrac, penggunaan defaultdict adalah cara yang cerdas dan nyaman cara untuk menghindari pembuatan manual setiap daftar players[team_name]

Akhirnya, ini akan memberi Anda:

  • kamus yang berisi nilai untuk name, position dan number kunci untuk setiap pemain
  • daftar tim berisi kamus pemain untuk setiap tim
  • kamus pemain yang menghubungkan daftar tim untuk setiap team_name

Ini adalah struktur data yang Anda inginkan, tetapi struktur lain dimungkinkan. Ingatlah untuk memikirkan struktur data Anda agar logis DAN mudah dimanipulasi.

1
Tryph 1 Februari 2020, 19:42

Anda tidak dapat membuat instance dict dengan 3 argumen, masalahnya adalah kenyataan bahwa Anda memiliki 3 variabel di zip: zip(number, name, position) yang ingin Anda gunakan untuk membuat dict , Anda hanya boleh memberikan 2 argumen sekaligus, kunci dan nilainya

Saya telah menulis ulang bagian terakhir Anda dari kode:

from collections import defaultdict
data = {}
players = defaultdict(list)

for team_name, team_link in team.items():
    player_page = requests.get(team_link)
    cont = soup(player_page.text, 'lxml')
    clud_ele = cont.find_all('span', attrs={'class' : 'playerCardInfo'})
    for i in clud_ele:
        num = i.select('span.number')[0].get_text(strip=True)
        number = 100 if num == '-' else num
        name = i.select('h4.name')[0].get_text(strip=True)
        position = i.select('span.position')[0].get_text(strip=True)
        players[team_name].append({'number': number, 'position': position, 'name': name})

keluaran:

defaultdict(list,
            {'Arsenal': [{'number': '1',
               'position': 'Goalkeeper',
               'name': 'Bernd Leno'},
              {'number': '26',
               'position': 'Goalkeeper',
               'name': 'Emiliano Martínez'},
              {'number': '33', 'position': 'Goalkeeper', 'name': 'Matt Macey'},
              {'number': '2',
               'position': 'Defender',
               'name': 'Héctor Bellerín'},
                 .......................
1
kederrac 1 Februari 2020, 18:58